nodenetcdf 4.9.32 → 4.9.34
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/LICENSE +19 -0
- package/README.md +23 -2
- package/package.json +1 -1
- package/src/Attribute.cpp +11 -49
- package/src/Attribute.h +91 -0
- package/src/Dimension.cpp +9 -19
- package/src/Dimension.h +71 -0
- package/src/File.cpp +21 -30
- package/src/File.h +71 -0
- package/src/Group.cpp +89 -56
- package/src/Group.h +131 -0
- package/src/Variable.cpp +188 -69
- package/src/Variable.h +282 -1
- package/src/nodenetcdfjs.h +41 -0
- package/test/json.js +7 -3
package/src/Variable.cpp
CHANGED
|
@@ -22,9 +22,7 @@ Variable::Variable(int id_, int parent_id_) noexcept
|
|
|
22
22
|
Wrap(obj);
|
|
23
23
|
const int retval = nc_inq_var(parent_id, id, nullptr, &type, &ndims, nullptr, nullptr);
|
|
24
24
|
if (retval != NC_NOERR)
|
|
25
|
-
{
|
|
26
25
|
throw_netcdf_error(isolate, retval);
|
|
27
|
-
}
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
void Variable::Init(v8::Local<v8::Object> exports)
|
|
@@ -104,8 +102,14 @@ void Variable::Write(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
|
104
102
|
|
|
105
103
|
if (args.Length() != obj->ndims + 1)
|
|
106
104
|
{
|
|
105
|
+
char name[NC_MAX_NAME + 1];
|
|
106
|
+
obj->get_name(name);
|
|
107
|
+
char error_msg[512];
|
|
108
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
109
|
+
"Variable.write() for '%s': Wrong number of arguments. Expected %d (position arguments) + 1 (value) = %d, but got %d",
|
|
110
|
+
name, obj->ndims, obj->ndims + 1, args.Length());
|
|
107
111
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
108
|
-
v8::String::NewFromUtf8(isolate,
|
|
112
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
109
113
|
.ToLocalChecked()));
|
|
110
114
|
return;
|
|
111
115
|
}
|
|
@@ -162,33 +166,48 @@ void Variable::Write(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
|
162
166
|
}
|
|
163
167
|
break;
|
|
164
168
|
default:
|
|
169
|
+
char name[NC_MAX_NAME + 1];
|
|
170
|
+
obj->get_name(name);
|
|
171
|
+
char error_msg[256];
|
|
172
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
173
|
+
"Variable.write() for '%s': Variable type %d not supported for write operations",
|
|
174
|
+
name, obj->type);
|
|
165
175
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
166
|
-
v8::String::NewFromUtf8(isolate,
|
|
176
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
167
177
|
.ToLocalChecked()));
|
|
168
178
|
return;
|
|
169
179
|
}
|
|
170
180
|
|
|
171
181
|
if (retval != NC_NOERR)
|
|
172
|
-
{
|
|
173
182
|
throw_netcdf_error(isolate, retval);
|
|
174
|
-
}
|
|
175
183
|
}
|
|
176
184
|
|
|
177
185
|
void Variable::WriteSlice(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
178
186
|
{
|
|
179
187
|
v8::Isolate *isolate = args.GetIsolate();
|
|
180
188
|
Variable *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
|
|
189
|
+
char name[NC_MAX_NAME + 1];
|
|
190
|
+
obj->get_name(name);
|
|
191
|
+
|
|
181
192
|
if (args.Length() != 2 * obj->ndims + 1)
|
|
182
193
|
{
|
|
194
|
+
char error_msg[512];
|
|
195
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
196
|
+
"Variable.writeSlice() for '%s': Wrong number of arguments. Expected %d pairs (pos,size) + 1 (array) = %d, but got %d",
|
|
197
|
+
name, obj->ndims, 2 * obj->ndims + 1, args.Length());
|
|
183
198
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
184
|
-
v8::String::NewFromUtf8(isolate,
|
|
199
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
185
200
|
.ToLocalChecked()));
|
|
186
201
|
return;
|
|
187
202
|
}
|
|
188
203
|
if (!args[2 * obj->ndims]->IsTypedArray())
|
|
189
204
|
{
|
|
205
|
+
char error_msg[256];
|
|
206
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
207
|
+
"Variable.writeSlice() for '%s': Last argument must be a typed array (Int8Array, Float32Array, etc.), but got %s",
|
|
208
|
+
name, *v8::String::Utf8Value(isolate, args[2 * obj->ndims]->TypeOf(isolate)));
|
|
190
209
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
191
|
-
v8::String::NewFromUtf8(isolate,
|
|
210
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
|
|
192
211
|
return;
|
|
193
212
|
}
|
|
194
213
|
size_t *pos = new size_t[obj->ndims];
|
|
@@ -204,44 +223,61 @@ void Variable::WriteSlice(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
|
204
223
|
v8::Local<v8::TypedArray> val = v8::Local<v8::TypedArray>::Cast(args[2 * obj->ndims]);
|
|
205
224
|
if (val->Length() != total_size)
|
|
206
225
|
{
|
|
226
|
+
char error_msg[512];
|
|
227
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
228
|
+
"Variable.writeSlice() for '%s': Array size mismatch. Expected %zu elements (product of sizes), but got %zu",
|
|
229
|
+
name, total_size, val->Length());
|
|
207
230
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
208
|
-
v8::String::NewFromUtf8(isolate,
|
|
231
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
|
|
209
232
|
delete[] pos;
|
|
210
233
|
delete[] size;
|
|
211
234
|
return;
|
|
212
235
|
}
|
|
213
236
|
|
|
214
237
|
bool correct_type;
|
|
238
|
+
const char *expected_type_name = nullptr;
|
|
215
239
|
switch (obj->type)
|
|
216
240
|
{
|
|
217
241
|
case NC_BYTE:
|
|
218
242
|
case NC_CHAR:
|
|
219
243
|
correct_type = val->IsInt8Array();
|
|
244
|
+
expected_type_name = "Int8Array";
|
|
220
245
|
break;
|
|
221
246
|
case NC_SHORT:
|
|
222
247
|
correct_type = val->IsInt16Array();
|
|
248
|
+
expected_type_name = "Int16Array";
|
|
223
249
|
break;
|
|
224
250
|
case NC_INT:
|
|
225
251
|
correct_type = val->IsInt32Array();
|
|
252
|
+
expected_type_name = "Int32Array";
|
|
226
253
|
break;
|
|
227
254
|
case NC_FLOAT:
|
|
228
255
|
correct_type = val->IsFloat32Array();
|
|
256
|
+
expected_type_name = "Float32Array";
|
|
229
257
|
break;
|
|
230
258
|
case NC_DOUBLE:
|
|
231
259
|
correct_type = val->IsFloat64Array();
|
|
260
|
+
expected_type_name = "Float64Array";
|
|
232
261
|
break;
|
|
233
262
|
case NC_UBYTE:
|
|
234
263
|
correct_type = val->IsUint8Array();
|
|
264
|
+
expected_type_name = "Uint8Array";
|
|
235
265
|
break;
|
|
236
266
|
case NC_USHORT:
|
|
237
267
|
correct_type = val->IsUint16Array();
|
|
268
|
+
expected_type_name = "Uint16Array";
|
|
238
269
|
break;
|
|
239
270
|
case NC_UINT:
|
|
240
271
|
correct_type = val->IsUint32Array();
|
|
272
|
+
expected_type_name = "Uint32Array";
|
|
241
273
|
break;
|
|
242
274
|
default:
|
|
275
|
+
char error_msg[256];
|
|
276
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
277
|
+
"Variable.writeSlice() for '%s': Variable type %d (%s) not supported for write operations",
|
|
278
|
+
name, obj->type, type_names[obj->type]);
|
|
243
279
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
244
|
-
v8::String::NewFromUtf8(isolate,
|
|
280
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
245
281
|
.ToLocalChecked()));
|
|
246
282
|
delete[] pos;
|
|
247
283
|
delete[] size;
|
|
@@ -249,8 +285,13 @@ void Variable::WriteSlice(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
|
249
285
|
}
|
|
250
286
|
if (!correct_type)
|
|
251
287
|
{
|
|
288
|
+
v8::String::Utf8Value actual_type(isolate, val->GetConstructorName());
|
|
289
|
+
char error_msg[512];
|
|
290
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
291
|
+
"Variable.writeSlice() for '%s': Array type mismatch. Variable type is %s, expected %s array, but got %s",
|
|
292
|
+
name, type_names[obj->type], expected_type_name, *actual_type);
|
|
252
293
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
253
|
-
v8::String::NewFromUtf8(isolate,
|
|
294
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
|
|
254
295
|
delete[] pos;
|
|
255
296
|
delete[] size;
|
|
256
297
|
return;
|
|
@@ -268,17 +309,28 @@ void Variable::WriteStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args
|
|
|
268
309
|
{
|
|
269
310
|
v8::Isolate *isolate = args.GetIsolate();
|
|
270
311
|
Variable *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
|
|
312
|
+
char name[NC_MAX_NAME + 1];
|
|
313
|
+
obj->get_name(name);
|
|
314
|
+
|
|
271
315
|
if (args.Length() != 3 * obj->ndims + 1)
|
|
272
316
|
{
|
|
317
|
+
char error_msg[512];
|
|
318
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
319
|
+
"Variable.writeStridedSlice() for '%s': Wrong number of arguments. Expected %d triplets (pos,size,stride) + 1 (array) = %d, but got %d",
|
|
320
|
+
name, obj->ndims, 3 * obj->ndims + 1, args.Length());
|
|
273
321
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
274
|
-
v8::String::NewFromUtf8(isolate,
|
|
322
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
275
323
|
.ToLocalChecked()));
|
|
276
324
|
return;
|
|
277
325
|
}
|
|
278
326
|
if (!args[3 * obj->ndims]->IsTypedArray())
|
|
279
327
|
{
|
|
328
|
+
char error_msg[256];
|
|
329
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
330
|
+
"Variable.writeStridedSlice() for '%s': Last argument must be a typed array, but got %s",
|
|
331
|
+
name, *v8::String::Utf8Value(isolate, args[3 * obj->ndims]->TypeOf(isolate)));
|
|
280
332
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
281
|
-
v8::String::NewFromUtf8(isolate,
|
|
333
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
|
|
282
334
|
return;
|
|
283
335
|
}
|
|
284
336
|
size_t *pos = new size_t[obj->ndims];
|
|
@@ -296,8 +348,12 @@ void Variable::WriteStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args
|
|
|
296
348
|
v8::Local<v8::TypedArray> val = v8::Local<v8::TypedArray>::Cast(args[3 * obj->ndims]);
|
|
297
349
|
if (val->Length() != total_size)
|
|
298
350
|
{
|
|
351
|
+
char error_msg[512];
|
|
352
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
353
|
+
"Variable.writeStridedSlice() for '%s': Array size mismatch. Expected %zu elements (product of sizes), but got %zu",
|
|
354
|
+
name, total_size, val->Length());
|
|
299
355
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
300
|
-
v8::String::NewFromUtf8(isolate,
|
|
356
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
|
|
301
357
|
delete[] pos;
|
|
302
358
|
delete[] size;
|
|
303
359
|
delete[] stride;
|
|
@@ -305,36 +361,49 @@ void Variable::WriteStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args
|
|
|
305
361
|
}
|
|
306
362
|
|
|
307
363
|
bool correct_type;
|
|
364
|
+
const char *expected_type_name = nullptr;
|
|
308
365
|
switch (obj->type)
|
|
309
366
|
{
|
|
310
367
|
case NC_BYTE:
|
|
311
368
|
case NC_CHAR:
|
|
312
369
|
correct_type = val->IsInt8Array();
|
|
370
|
+
expected_type_name = "Int8Array";
|
|
313
371
|
break;
|
|
314
372
|
case NC_SHORT:
|
|
315
373
|
correct_type = val->IsInt16Array();
|
|
374
|
+
expected_type_name = "Int16Array";
|
|
316
375
|
break;
|
|
317
376
|
case NC_INT:
|
|
318
377
|
correct_type = val->IsInt32Array();
|
|
378
|
+
expected_type_name = "Int32Array";
|
|
319
379
|
break;
|
|
320
380
|
case NC_FLOAT:
|
|
321
381
|
correct_type = val->IsFloat32Array();
|
|
382
|
+
expected_type_name = "Float32Array";
|
|
322
383
|
break;
|
|
323
384
|
case NC_DOUBLE:
|
|
324
385
|
correct_type = val->IsFloat64Array();
|
|
386
|
+
expected_type_name = "Float64Array";
|
|
325
387
|
break;
|
|
326
388
|
case NC_UBYTE:
|
|
327
389
|
correct_type = val->IsUint8Array();
|
|
390
|
+
expected_type_name = "Uint8Array";
|
|
328
391
|
break;
|
|
329
392
|
case NC_USHORT:
|
|
330
393
|
correct_type = val->IsUint16Array();
|
|
394
|
+
expected_type_name = "Uint16Array";
|
|
331
395
|
break;
|
|
332
396
|
case NC_UINT:
|
|
333
397
|
correct_type = val->IsUint32Array();
|
|
398
|
+
expected_type_name = "Uint32Array";
|
|
334
399
|
break;
|
|
335
400
|
default:
|
|
401
|
+
char error_msg[256];
|
|
402
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
403
|
+
"Variable.writeStridedSlice() for '%s': Variable type %d (%s) not supported for write operations",
|
|
404
|
+
name, obj->type, type_names[obj->type]);
|
|
336
405
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
337
|
-
v8::String::NewFromUtf8(isolate,
|
|
406
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
338
407
|
.ToLocalChecked()));
|
|
339
408
|
delete[] pos;
|
|
340
409
|
delete[] size;
|
|
@@ -343,8 +412,13 @@ void Variable::WriteStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args
|
|
|
343
412
|
}
|
|
344
413
|
if (!correct_type)
|
|
345
414
|
{
|
|
415
|
+
v8::String::Utf8Value actual_type(isolate, val->GetConstructorName());
|
|
416
|
+
char error_msg[512];
|
|
417
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
418
|
+
"Variable.writeStridedSlice() for '%s': Array type mismatch. Variable type is %s, expected %s array, but got %s",
|
|
419
|
+
name, type_names[obj->type], expected_type_name, *actual_type);
|
|
346
420
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
347
|
-
v8::String::NewFromUtf8(isolate,
|
|
421
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
|
|
348
422
|
delete[] pos;
|
|
349
423
|
delete[] size;
|
|
350
424
|
delete[] stride;
|
|
@@ -352,9 +426,7 @@ void Variable::WriteStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args
|
|
|
352
426
|
}
|
|
353
427
|
int retval = nc_put_vars(obj->parent_id, obj->id, pos, size, stride, val->Buffer()->GetBackingStore()->Data());
|
|
354
428
|
if (retval != NC_NOERR)
|
|
355
|
-
{
|
|
356
429
|
throw_netcdf_error(isolate, retval);
|
|
357
|
-
}
|
|
358
430
|
delete[] pos;
|
|
359
431
|
delete[] size;
|
|
360
432
|
delete[] stride;
|
|
@@ -364,17 +436,28 @@ void Variable::Read(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
|
364
436
|
{
|
|
365
437
|
v8::Isolate *isolate = args.GetIsolate();
|
|
366
438
|
Variable *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
|
|
439
|
+
char name[NC_MAX_NAME + 1];
|
|
440
|
+
obj->get_name(name);
|
|
441
|
+
|
|
367
442
|
if (args.Length() != obj->ndims)
|
|
368
443
|
{
|
|
444
|
+
char error_msg[512];
|
|
445
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
446
|
+
"Variable.read() for '%s': Wrong number of arguments. Expected %d position indices (one per dimension), but got %d",
|
|
447
|
+
name, obj->ndims, args.Length());
|
|
369
448
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
370
|
-
v8::String::NewFromUtf8(isolate,
|
|
449
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
371
450
|
.ToLocalChecked()));
|
|
372
451
|
return;
|
|
373
452
|
}
|
|
374
453
|
if (obj->type < NC_BYTE || obj->type > NC_UINT)
|
|
375
454
|
{
|
|
455
|
+
char error_msg[256];
|
|
456
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
457
|
+
"Variable.read() for '%s': Variable type %d not supported for read operations",
|
|
458
|
+
name, obj->type);
|
|
376
459
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
377
|
-
v8::String::NewFromUtf8(isolate,
|
|
460
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
378
461
|
.ToLocalChecked()));
|
|
379
462
|
return;
|
|
380
463
|
}
|
|
@@ -446,13 +529,9 @@ void Variable::Read(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
|
446
529
|
break;
|
|
447
530
|
}
|
|
448
531
|
if (retval != NC_NOERR)
|
|
449
|
-
{
|
|
450
532
|
throw_netcdf_error(isolate, retval);
|
|
451
|
-
}
|
|
452
533
|
else
|
|
453
|
-
{
|
|
454
534
|
args.GetReturnValue().Set(result);
|
|
455
|
-
}
|
|
456
535
|
delete[] pos;
|
|
457
536
|
delete[] size;
|
|
458
537
|
}
|
|
@@ -461,17 +540,28 @@ void Variable::ReadSlice(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
|
461
540
|
{
|
|
462
541
|
v8::Isolate *isolate = args.GetIsolate();
|
|
463
542
|
Variable *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
|
|
543
|
+
char name[NC_MAX_NAME + 1];
|
|
544
|
+
obj->get_name(name);
|
|
545
|
+
|
|
464
546
|
if (args.Length() != 2 * obj->ndims)
|
|
465
547
|
{
|
|
548
|
+
char error_msg[512];
|
|
549
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
550
|
+
"Variable.readSlice() for '%s': Wrong number of arguments. Expected %d pairs (pos,size) = %d arguments, but got %d",
|
|
551
|
+
name, obj->ndims, 2 * obj->ndims, args.Length());
|
|
466
552
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
467
|
-
v8::String::NewFromUtf8(isolate,
|
|
553
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
468
554
|
.ToLocalChecked()));
|
|
469
555
|
return;
|
|
470
556
|
}
|
|
471
557
|
if (obj->type < NC_BYTE || obj->type > NC_UINT)
|
|
472
558
|
{
|
|
559
|
+
char error_msg[256];
|
|
560
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
561
|
+
"Variable.readSlice() for '%s': Variable type %d not supported for read operations",
|
|
562
|
+
name, obj->type);
|
|
473
563
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
474
|
-
v8::String::NewFromUtf8(isolate,
|
|
564
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
475
565
|
.ToLocalChecked()));
|
|
476
566
|
return;
|
|
477
567
|
}
|
|
@@ -525,8 +615,12 @@ void Variable::ReadSlice(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
|
525
615
|
result = v8::Uint32Array::New(buffer, 0, total_size);
|
|
526
616
|
break;
|
|
527
617
|
default:
|
|
618
|
+
char error_msg[256];
|
|
619
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
620
|
+
"Variable.readSlice() for '%s': Variable type %d (%s) not supported for creating typed array result",
|
|
621
|
+
name, obj->type, type_names[obj->type]);
|
|
528
622
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
529
|
-
v8::String::NewFromUtf8(isolate,
|
|
623
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
530
624
|
.ToLocalChecked()));
|
|
531
625
|
delete[] pos;
|
|
532
626
|
delete[] size;
|
|
@@ -541,17 +635,28 @@ void Variable::ReadStridedSlice(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
|
541
635
|
{
|
|
542
636
|
v8::Isolate *isolate = args.GetIsolate();
|
|
543
637
|
Variable *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
|
|
638
|
+
char name[NC_MAX_NAME + 1];
|
|
639
|
+
obj->get_name(name);
|
|
640
|
+
|
|
544
641
|
if (args.Length() != 3 * obj->ndims)
|
|
545
642
|
{
|
|
643
|
+
char error_msg[512];
|
|
644
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
645
|
+
"Variable.readStridedSlice() for '%s': Wrong number of arguments. Expected %d triplets (pos,size,stride) = %d arguments, but got %d",
|
|
646
|
+
name, obj->ndims, 3 * obj->ndims, args.Length());
|
|
546
647
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
547
|
-
v8::String::NewFromUtf8(isolate,
|
|
648
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
548
649
|
.ToLocalChecked()));
|
|
549
650
|
return;
|
|
550
651
|
}
|
|
551
652
|
if (obj->type < NC_BYTE || obj->type > NC_UINT)
|
|
552
653
|
{
|
|
654
|
+
char error_msg[256];
|
|
655
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
656
|
+
"Variable.readStridedSlice() for '%s': Variable type %d not supported for read operations",
|
|
657
|
+
name, obj->type);
|
|
553
658
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
554
|
-
v8::String::NewFromUtf8(isolate,
|
|
659
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
555
660
|
.ToLocalChecked()));
|
|
556
661
|
return;
|
|
557
662
|
}
|
|
@@ -618,10 +723,17 @@ void Variable::AddAttribute(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
|
618
723
|
{
|
|
619
724
|
v8::Isolate *isolate = args.GetIsolate();
|
|
620
725
|
Variable *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
|
|
726
|
+
char var_name[NC_MAX_NAME + 1];
|
|
727
|
+
obj->get_name(var_name);
|
|
728
|
+
|
|
621
729
|
if (args.Length() < 3)
|
|
622
730
|
{
|
|
731
|
+
char error_msg[512];
|
|
732
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
733
|
+
"Variable.addAttribute() for '%s': Wrong number of arguments. Expected 3 (name, type, value), but got %d",
|
|
734
|
+
var_name, args.Length());
|
|
623
735
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
624
|
-
v8::String::NewFromUtf8(isolate,
|
|
736
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal)
|
|
625
737
|
.ToLocalChecked()));
|
|
626
738
|
return;
|
|
627
739
|
}
|
|
@@ -633,8 +745,17 @@ void Variable::AddAttribute(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
|
633
745
|
int type = get_type(type_str);
|
|
634
746
|
if (type == NC2_ERR)
|
|
635
747
|
{
|
|
748
|
+
std::string attr_name = *v8::String::Utf8Value(
|
|
749
|
+
#if NODE_MAJOR_VERSION >= 8
|
|
750
|
+
isolate,
|
|
751
|
+
#endif
|
|
752
|
+
args[0]);
|
|
753
|
+
char error_msg[512];
|
|
754
|
+
snprintf(error_msg, sizeof(error_msg),
|
|
755
|
+
"Variable.addAttribute() for '%s': Unknown attribute type '%s' for attribute '%s'. Valid types are: byte, char, short, int, float, double, ubyte, ushort, uint",
|
|
756
|
+
var_name, type_str.c_str(), attr_name.c_str());
|
|
636
757
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
637
|
-
v8::String::NewFromUtf8(isolate,
|
|
758
|
+
v8::String::NewFromUtf8(isolate, error_msg, v8::NewStringType::kNormal).ToLocalChecked()));
|
|
638
759
|
return;
|
|
639
760
|
}
|
|
640
761
|
Attribute *res = new Attribute(*v8::String::Utf8Value(
|
|
@@ -727,9 +848,7 @@ void Variable::GetName(v8::Local<v8::String> property, const v8::PropertyCallbac
|
|
|
727
848
|
Variable *obj = node::ObjectWrap::Unwrap<Variable>(info.Holder());
|
|
728
849
|
char name[NC_MAX_NAME + 1];
|
|
729
850
|
if (obj->get_name(name))
|
|
730
|
-
{
|
|
731
851
|
info.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kNormal).ToLocalChecked());
|
|
732
|
-
}
|
|
733
852
|
}
|
|
734
853
|
|
|
735
854
|
void Variable::SetName(v8::Local<v8::String> property, v8::Local<v8::Value> val,
|
|
@@ -792,17 +911,11 @@ void Variable::SetEndianness(v8::Local<v8::String> property, v8::Local<v8::Value
|
|
|
792
911
|
val->ToString(isolate->GetCurrentContext()).ToLocalChecked());
|
|
793
912
|
int v;
|
|
794
913
|
if (arg == "little")
|
|
795
|
-
{
|
|
796
914
|
v = NC_ENDIAN_LITTLE;
|
|
797
|
-
}
|
|
798
915
|
else if (arg == "big")
|
|
799
|
-
{
|
|
800
916
|
v = NC_ENDIAN_BIG;
|
|
801
|
-
}
|
|
802
917
|
else if (arg == "native")
|
|
803
|
-
{
|
|
804
918
|
v = NC_ENDIAN_NATIVE;
|
|
805
|
-
}
|
|
806
919
|
else
|
|
807
920
|
{
|
|
808
921
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
@@ -856,13 +969,9 @@ void Variable::SetChecksumMode(v8::Local<v8::String> property, v8::Local<v8::Val
|
|
|
856
969
|
val->ToString(isolate->GetCurrentContext()).ToLocalChecked());
|
|
857
970
|
int v;
|
|
858
971
|
if (arg == "none")
|
|
859
|
-
{
|
|
860
972
|
v = NC_NOCHECKSUM;
|
|
861
|
-
}
|
|
862
973
|
else if (arg == "fletcher32")
|
|
863
|
-
{
|
|
864
974
|
v = NC_FLETCHER32;
|
|
865
|
-
}
|
|
866
975
|
else
|
|
867
976
|
{
|
|
868
977
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
@@ -916,13 +1025,9 @@ void Variable::SetChunkMode(v8::Local<v8::String> property, v8::Local<v8::Value>
|
|
|
916
1025
|
val->ToString(isolate->GetCurrentContext()).ToLocalChecked());
|
|
917
1026
|
int v;
|
|
918
1027
|
if (arg == "contiguous")
|
|
919
|
-
{
|
|
920
1028
|
v = NC_CONTIGUOUS;
|
|
921
|
-
}
|
|
922
1029
|
else if (arg == "chunked")
|
|
923
|
-
{
|
|
924
1030
|
v = NC_CHUNKED;
|
|
925
|
-
}
|
|
926
1031
|
else
|
|
927
1032
|
{
|
|
928
1033
|
isolate->ThrowException(v8::Exception::TypeError(
|
|
@@ -946,9 +1051,7 @@ void Variable::SetChunkMode(v8::Local<v8::String> property, v8::Local<v8::Value>
|
|
|
946
1051
|
}
|
|
947
1052
|
retval = nc_def_var_chunking(obj->parent_id, obj->id, v, sizes);
|
|
948
1053
|
if (retval != NC_NOERR)
|
|
949
|
-
{
|
|
950
1054
|
throw_netcdf_error(isolate, retval);
|
|
951
|
-
}
|
|
952
1055
|
delete[] sizes;
|
|
953
1056
|
}
|
|
954
1057
|
|
|
@@ -966,9 +1069,7 @@ void Variable::GetChunkSizes(v8::Local<v8::String> property, const v8::PropertyC
|
|
|
966
1069
|
}
|
|
967
1070
|
v8::Local<v8::Array> result = v8::Array::New(isolate);
|
|
968
1071
|
for (int i = 0; i < obj->ndims; i++)
|
|
969
|
-
{
|
|
970
1072
|
result->Set(isolate->GetCurrentContext(), i, v8::Integer::New(isolate, i));
|
|
971
|
-
}
|
|
972
1073
|
info.GetReturnValue().Set(result);
|
|
973
1074
|
delete[] sizes;
|
|
974
1075
|
}
|
|
@@ -1005,17 +1106,13 @@ void Variable::SetChunkSizes(v8::Local<v8::String> property, v8::Local<v8::Value
|
|
|
1005
1106
|
}
|
|
1006
1107
|
size_t *sizes = new size_t[obj->ndims];
|
|
1007
1108
|
for (int i = 0; i < obj->ndims; i++)
|
|
1008
|
-
{
|
|
1009
1109
|
sizes[i] = array->Get(isolate->GetCurrentContext(), i)
|
|
1010
1110
|
.ToLocalChecked()
|
|
1011
1111
|
->Uint32Value(isolate->GetCurrentContext())
|
|
1012
1112
|
.ToChecked();
|
|
1013
|
-
}
|
|
1014
1113
|
retval = nc_def_var_chunking(obj->parent_id, obj->id, v, sizes);
|
|
1015
1114
|
if (retval != NC_NOERR)
|
|
1016
|
-
{
|
|
1017
1115
|
throw_netcdf_error(isolate, retval);
|
|
1018
|
-
}
|
|
1019
1116
|
delete[] sizes;
|
|
1020
1117
|
}
|
|
1021
1118
|
|
|
@@ -1066,9 +1163,7 @@ void Variable::SetFillMode(v8::Local<v8::String> property, v8::Local<v8::Value>
|
|
|
1066
1163
|
}
|
|
1067
1164
|
retval = nc_def_var_fill(obj->parent_id, obj->id, v, value);
|
|
1068
1165
|
if (retval != NC_NOERR)
|
|
1069
|
-
{
|
|
1070
1166
|
throw_netcdf_error(isolate, retval);
|
|
1071
|
-
}
|
|
1072
1167
|
delete[] value;
|
|
1073
1168
|
}
|
|
1074
1169
|
|
|
@@ -1211,9 +1306,7 @@ void Variable::SetFillValue(v8::Local<v8::String> property, v8::Local<v8::Value>
|
|
|
1211
1306
|
return;
|
|
1212
1307
|
}
|
|
1213
1308
|
if (retval != NC_NOERR)
|
|
1214
|
-
{
|
|
1215
1309
|
throw_netcdf_error(isolate, retval);
|
|
1216
|
-
}
|
|
1217
1310
|
}
|
|
1218
1311
|
|
|
1219
1312
|
void Variable::GetCompressionShuffle(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info)
|
|
@@ -1299,9 +1392,7 @@ void Variable::SetCompressionDeflate(v8::Local<v8::String> property, v8::Local<v
|
|
|
1299
1392
|
}
|
|
1300
1393
|
retval = nc_def_var_deflate(obj->parent_id, obj->id, v1, v, v2);
|
|
1301
1394
|
if (retval != NC_NOERR)
|
|
1302
|
-
{
|
|
1303
1395
|
throw_netcdf_error(isolate, retval);
|
|
1304
|
-
}
|
|
1305
1396
|
}
|
|
1306
1397
|
|
|
1307
1398
|
void Variable::GetCompressionLevel(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value> &info)
|
|
@@ -1358,7 +1449,6 @@ void Variable::ToJSON(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
|
1358
1449
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
|
1359
1450
|
const auto *obj = node::ObjectWrap::Unwrap<Variable>(args.Holder());
|
|
1360
1451
|
|
|
1361
|
-
// Use internalized strings for better performance
|
|
1362
1452
|
v8::Local<v8::String> id_str = v8::String::NewFromUtf8Literal(isolate, "id");
|
|
1363
1453
|
v8::Local<v8::String> name_str = v8::String::NewFromUtf8Literal(isolate, "name");
|
|
1364
1454
|
v8::Local<v8::String> type_str = v8::String::NewFromUtf8Literal(isolate, "type");
|
|
@@ -1367,41 +1457,70 @@ void Variable::ToJSON(const v8::FunctionCallbackInfo<v8::Value> &args)
|
|
|
1367
1457
|
|
|
1368
1458
|
v8::Local<v8::Object> json = v8::Object::New(isolate);
|
|
1369
1459
|
|
|
1370
|
-
// Add id
|
|
1371
1460
|
(void)json->CreateDataProperty(context, id_str, v8::Integer::New(isolate, obj->id));
|
|
1372
1461
|
|
|
1373
|
-
// Add name
|
|
1374
1462
|
char name[NC_MAX_NAME + 1];
|
|
1375
1463
|
if (obj->get_name(name))
|
|
1376
|
-
{
|
|
1377
1464
|
(void)json->CreateDataProperty(context, name_str,
|
|
1378
1465
|
v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kInternalized).ToLocalChecked());
|
|
1379
|
-
}
|
|
1380
1466
|
|
|
1381
1467
|
// Add type
|
|
1382
1468
|
const char *type_name = (obj->type < NC_BYTE || obj->type > NC_UINT) ? "unknown" : type_names[obj->type];
|
|
1383
1469
|
(void)json->CreateDataProperty(context, type_str,
|
|
1384
1470
|
v8::String::NewFromUtf8(isolate, type_name, v8::NewStringType::kInternalized).ToLocalChecked());
|
|
1385
1471
|
|
|
1386
|
-
// Dimensions are already an array, just add them
|
|
1387
1472
|
v8::Local<v8::Value> dimensions = args.Holder()->Get(context, dimensions_str).ToLocalChecked();
|
|
1388
1473
|
if (dimensions->IsArray())
|
|
1389
1474
|
{
|
|
1390
|
-
|
|
1475
|
+
v8::Local<v8::Array> dimsArray = v8::Local<v8::Array>::Cast(dimensions);
|
|
1476
|
+
v8::Local<v8::Array> newDimsArray = v8::Array::New(isolate, dimsArray->Length());
|
|
1477
|
+
v8::Local<v8::String> toJSONStr = v8::String::NewFromUtf8Literal(isolate, "toJSON");
|
|
1478
|
+
|
|
1479
|
+
for (uint32_t i = 0; i < dimsArray->Length(); i++)
|
|
1480
|
+
{
|
|
1481
|
+
v8::Local<v8::Value> value = dimsArray->Get(context, i).ToLocalChecked();
|
|
1482
|
+
|
|
1483
|
+
// Call toJSON if available to ensure proper serialization
|
|
1484
|
+
if (value->IsObject())
|
|
1485
|
+
{
|
|
1486
|
+
v8::Local<v8::Object> valueObj = value->ToObject(context).ToLocalChecked();
|
|
1487
|
+
v8::Local<v8::Value> toJSON = valueObj->Get(context, toJSONStr).ToLocalChecked();
|
|
1488
|
+
if (toJSON->IsFunction())
|
|
1489
|
+
{
|
|
1490
|
+
v8::Local<v8::Function> toJSONFunc = v8::Local<v8::Function>::Cast(toJSON);
|
|
1491
|
+
value = toJSONFunc->Call(context, valueObj, 0, nullptr).ToLocalChecked();
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
(void)newDimsArray->Set(context, i, value);
|
|
1495
|
+
}
|
|
1496
|
+
(void)json->CreateDataProperty(context, dimensions_str, newDimsArray);
|
|
1391
1497
|
}
|
|
1392
1498
|
|
|
1393
|
-
// Convert attributes object to array
|
|
1499
|
+
// Convert attributes object to array, calling toJSON on each item
|
|
1394
1500
|
v8::Local<v8::Value> attributes = args.Holder()->Get(context, attributes_str).ToLocalChecked();
|
|
1395
1501
|
if (attributes->IsObject() && !attributes->IsNull())
|
|
1396
1502
|
{
|
|
1397
1503
|
v8::Local<v8::Object> attrsObj = attributes->ToObject(context).ToLocalChecked();
|
|
1398
1504
|
v8::Local<v8::Array> propNames = attrsObj->GetOwnPropertyNames(context).ToLocalChecked();
|
|
1399
1505
|
v8::Local<v8::Array> attrsArray = v8::Array::New(isolate, propNames->Length());
|
|
1506
|
+
v8::Local<v8::String> toJSONStr = v8::String::NewFromUtf8Literal(isolate, "toJSON");
|
|
1400
1507
|
|
|
1401
1508
|
for (uint32_t i = 0; i < propNames->Length(); i++)
|
|
1402
1509
|
{
|
|
1403
1510
|
v8::Local<v8::Value> key = propNames->Get(context, i).ToLocalChecked();
|
|
1404
1511
|
v8::Local<v8::Value> value = attrsObj->Get(context, key).ToLocalChecked();
|
|
1512
|
+
|
|
1513
|
+
// Call toJSON if available to ensure proper serialization
|
|
1514
|
+
if (value->IsObject())
|
|
1515
|
+
{
|
|
1516
|
+
v8::Local<v8::Object> valueObj = value->ToObject(context).ToLocalChecked();
|
|
1517
|
+
v8::Local<v8::Value> toJSON = valueObj->Get(context, toJSONStr).ToLocalChecked();
|
|
1518
|
+
if (toJSON->IsFunction())
|
|
1519
|
+
{
|
|
1520
|
+
v8::Local<v8::Function> toJSONFunc = v8::Local<v8::Function>::Cast(toJSON);
|
|
1521
|
+
value = toJSONFunc->Call(context, valueObj, 0, nullptr).ToLocalChecked();
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1405
1524
|
(void)attrsArray->Set(context, i, value);
|
|
1406
1525
|
}
|
|
1407
1526
|
(void)json->CreateDataProperty(context, attributes_str, attrsArray);
|