netcdf 0.1.0

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.
@@ -0,0 +1,349 @@
1
+ #include "internal.h"
2
+
3
+ static VALUE
4
+ rb_nc_create (int argc, VALUE *argv, VALUE self)
5
+ {
6
+ VALUE rpath, rmode;
7
+ int cmode, ncid;
8
+
9
+ rb_scan_args(argc, argv, "11", &rpath, &rmode);
10
+ cmode = NIL_P(rmode) ? NC_CLOBBER : NUM2INT(rmode);
11
+ NC_CHECK(nc_create(StringValueCStr(rpath), cmode, &ncid));
12
+ return INT2NUM(ncid);
13
+ }
14
+
15
+ static VALUE
16
+ rb_nc_open (int argc, VALUE *argv, VALUE self)
17
+ {
18
+ VALUE rpath, rmode;
19
+ int omode, ncid;
20
+
21
+ rb_scan_args(argc, argv, "11", &rpath, &rmode);
22
+ omode = NIL_P(rmode) ? NC_NOWRITE : NUM2INT(rmode);
23
+ NC_CHECK(nc_open(StringValueCStr(rpath), omode, &ncid));
24
+ return INT2NUM(ncid);
25
+ }
26
+
27
+ #ifdef HAVE_NC_OPEN_MEM
28
+ /* nc_open_mem passes the buffer to libnetcdf with NC_MEMIO_LOCKED: the
29
+ library reads the caller's memory in place (it does not copy it) until
30
+ the file is closed, and never frees it. A Ruby String's buffer may be
31
+ moved by compaction or freed while the file is still open, so a
32
+ malloc'd copy is handed over instead and kept in this list until the
33
+ file is closed (nc_close / nc_abort / nc_close_memio).
34
+
35
+ nc_open_memio without NC_MEMIO_LOCKED would let the library own and
36
+ free the copy, but whether it frees the memory when the open fails
37
+ depends on where it fails (netcdf-c 4.10.1 frees it for a broken
38
+ header but not for an unknown format), so the copy is owned here. */
39
+ typedef struct mem_image {
40
+ int ncid;
41
+ void *memory;
42
+ struct mem_image *next;
43
+ } mem_image_t;
44
+
45
+ static mem_image_t *mem_images = NULL;
46
+
47
+ /* Free the copies whose files are no longer open. Each stored ncid is
48
+ asked whether it is still open instead of being matched against the id
49
+ passed to nc_close, so a file closed through another id is covered as
50
+ well. Returns true if `memory` was one of the freed copies. */
51
+ static bool
52
+ mem_image_release_closed (const void *memory)
53
+ {
54
+ mem_image_t **pp;
55
+ mem_image_t *m;
56
+ bool released;
57
+ int fmt;
58
+
59
+ released = false;
60
+ pp = &mem_images;
61
+ while ( *pp ) {
62
+ m = *pp;
63
+ if ( nc_inq_format(m->ncid, &fmt) == NC_EBADID ) {
64
+ if ( m->memory == memory ) {
65
+ released = true;
66
+ }
67
+ *pp = m->next;
68
+ free(m->memory);
69
+ xfree(m);
70
+ }
71
+ else {
72
+ pp = &m->next;
73
+ }
74
+ }
75
+ return released;
76
+ }
77
+
78
+ static VALUE
79
+ rb_nc_open_mem (VALUE self, VALUE rpath, VALUE rmode, VALUE rbytes)
80
+ {
81
+ const char *path;
82
+ mem_image_t *m;
83
+ long len;
84
+ int omode, st;
85
+
86
+ omode = NUM2INT(rmode);
87
+ path = StringValueCStr(rpath);
88
+ StringValue(rbytes);
89
+ len = RSTRING_LEN(rbytes);
90
+ /* libnetcdf keeps using this memory until the file is closed. */
91
+ m = ALLOC(mem_image_t);
92
+ m->memory = malloc(len > 0 ? (size_t) len : 1);
93
+ if ( ! m->memory ) {
94
+ xfree(m);
95
+ rb_memerror();
96
+ }
97
+ memcpy(m->memory, RSTRING_PTR(rbytes), (size_t) len);
98
+ st = nc_open_mem(path, omode, (size_t) len, m->memory, &m->ncid);
99
+ if ( st != NC_NOERR ) {
100
+ free(m->memory);
101
+ xfree(m);
102
+ nc_raise(st);
103
+ }
104
+ mem_image_release_closed(NULL);
105
+ m->next = mem_images;
106
+ mem_images = m;
107
+ return INT2NUM(m->ncid);
108
+ }
109
+ #else
110
+ # define mem_image_release_closed(memory) false
111
+ #endif
112
+
113
+ #ifdef HAVE_NC_CREATE_MEM
114
+ static VALUE
115
+ rb_nc_create_mem (int argc, VALUE *argv, VALUE self)
116
+ {
117
+ VALUE rpath, rmode, rinitialsize;
118
+ int cmode, ncid;
119
+ size_t isz;
120
+
121
+ rb_scan_args(argc, argv, "12", &rpath, &rmode, &rinitialsize);
122
+ cmode = NIL_P(rmode) ? NC_NETCDF4 : NUM2INT(rmode);
123
+ isz = NIL_P(rinitialsize) ? 0 : NUM2SIZET(rinitialsize);
124
+ NC_CHECK(nc_create_mem(StringValueCStr(rpath), cmode, isz, &ncid));
125
+ return INT2NUM(ncid);
126
+ }
127
+ #endif
128
+
129
+ #ifdef HAVE_NC_CLOSE_MEMIO
130
+ static VALUE
131
+ rb_nc_close_memio (VALUE self, VALUE rncid)
132
+ {
133
+ NC_memio memio;
134
+ VALUE out;
135
+
136
+ memset(&memio, 0, sizeof(memio));
137
+ /* flags=0: ownership of memio.memory transfers to us; we must free it. */
138
+ NC_CHECK(nc_close_memio(NUM2INT(rncid), &memio));
139
+ out = rb_str_new((const char *) memio.memory, (long) memio.size);
140
+ /* For a handle from nc_open_mem, memio.memory is the copy made there;
141
+ mem_image_release_closed frees it (once), so it is not freed here. */
142
+ if ( ! mem_image_release_closed(memio.memory) ) {
143
+ free(memio.memory);
144
+ }
145
+ return out;
146
+ }
147
+ #endif
148
+
149
+ static VALUE
150
+ rb_nc_close (VALUE self, VALUE rncid)
151
+ {
152
+ NC_CHECK(nc_close(NUM2INT(rncid)));
153
+ mem_image_release_closed(NULL);
154
+ return Qnil;
155
+ }
156
+
157
+ static VALUE
158
+ rb_nc_abort (VALUE self, VALUE rncid)
159
+ {
160
+ NC_CHECK(nc_abort(NUM2INT(rncid)));
161
+ mem_image_release_closed(NULL);
162
+ return Qnil;
163
+ }
164
+
165
+ static VALUE
166
+ rb_nc_sync (VALUE self, VALUE rncid)
167
+ {
168
+ NC_CHECK(nc_sync(NUM2INT(rncid)));
169
+ return Qnil;
170
+ }
171
+
172
+ static VALUE
173
+ rb_nc_redef (VALUE self, VALUE rncid)
174
+ {
175
+ NC_CHECK(nc_redef(NUM2INT(rncid)));
176
+ return Qnil;
177
+ }
178
+
179
+ static VALUE
180
+ rb_nc_enddef (VALUE self, VALUE rncid)
181
+ {
182
+ NC_CHECK(nc_enddef(NUM2INT(rncid)));
183
+ return Qnil;
184
+ }
185
+
186
+ static VALUE
187
+ rb_nc_inq (VALUE self, VALUE rncid)
188
+ {
189
+ VALUE rudim;
190
+ int ndims, nvars, natts, unlimdim;
191
+
192
+ NC_CHECK(nc_inq(NUM2INT(rncid), &ndims, &nvars, &natts, &unlimdim));
193
+ rudim = ( unlimdim < 0 ) ? Qnil : INT2NUM(unlimdim);
194
+ return rb_ary_new_from_args(4, INT2NUM(ndims), INT2NUM(nvars), INT2NUM(natts), rudim);
195
+ }
196
+
197
+ static VALUE
198
+ rb_nc_inq_ndims (VALUE self, VALUE rncid)
199
+ {
200
+ int n;
201
+
202
+ NC_CHECK(nc_inq_ndims(NUM2INT(rncid), &n));
203
+ return INT2NUM(n);
204
+ }
205
+
206
+ static VALUE
207
+ rb_nc_inq_nvars (VALUE self, VALUE rncid)
208
+ {
209
+ int n;
210
+
211
+ NC_CHECK(nc_inq_nvars(NUM2INT(rncid), &n));
212
+ return INT2NUM(n);
213
+ }
214
+
215
+ static VALUE
216
+ rb_nc_inq_natts (VALUE self, VALUE rncid)
217
+ {
218
+ int n;
219
+
220
+ NC_CHECK(nc_inq_natts(NUM2INT(rncid), &n));
221
+ return INT2NUM(n);
222
+ }
223
+
224
+ static VALUE
225
+ rb_nc_inq_unlimdim (VALUE self, VALUE rncid)
226
+ {
227
+ int d;
228
+
229
+ NC_CHECK(nc_inq_unlimdim(NUM2INT(rncid), &d));
230
+ return ( d < 0 ) ? Qnil : INT2NUM(d);
231
+ }
232
+
233
+ #ifdef HAVE_NC_INQ_PATH
234
+ static VALUE
235
+ rb_nc_inq_path (VALUE self, VALUE rncid)
236
+ {
237
+ VALUE out;
238
+ size_t len;
239
+
240
+ NC_CHECK(nc_inq_path(NUM2INT(rncid), &len, NULL));
241
+ out = rb_str_buf_new((long) len);
242
+ rb_str_set_len(out, (long) len);
243
+ NC_CHECK(nc_inq_path(NUM2INT(rncid), NULL, RSTRING_PTR(out)));
244
+ return out;
245
+ }
246
+ #endif
247
+
248
+ static VALUE
249
+ rb_nc_inq_format (VALUE self, VALUE rncid)
250
+ {
251
+ int fmt;
252
+
253
+ NC_CHECK(nc_inq_format(NUM2INT(rncid), &fmt));
254
+ return INT2NUM(fmt);
255
+ }
256
+
257
+ #ifdef HAVE_NC_INQ_FORMAT_EXTENDED
258
+ static VALUE
259
+ rb_nc_inq_format_extended (VALUE self, VALUE rncid)
260
+ {
261
+ int fmt, mode;
262
+
263
+ NC_CHECK(nc_inq_format_extended(NUM2INT(rncid), &fmt, &mode));
264
+ return rb_ary_new_from_args(2, INT2NUM(fmt), INT2NUM(mode));
265
+ }
266
+ #endif
267
+
268
+ static VALUE
269
+ rb_nc_inq_libvers (VALUE self)
270
+ {
271
+ return rb_str_new_cstr(nc_inq_libvers());
272
+ }
273
+
274
+ static VALUE
275
+ rb_nc_inq_type (VALUE self, VALUE rncid, VALUE rxtype)
276
+ {
277
+ char name[NC_MAX_NAME + 1];
278
+ size_t sz;
279
+
280
+ NC_CHECK(nc_inq_type(NUM2INT(rncid), NUM2INT(rxtype), name, &sz));
281
+ return rb_ary_new_from_args(2, rb_utf8_str_new_cstr(name), SIZET2NUM(sz));
282
+ }
283
+
284
+ static VALUE
285
+ rb_nc_set_fill (VALUE self, VALUE rncid, VALUE rmode)
286
+ {
287
+ int old;
288
+
289
+ NC_CHECK(nc_set_fill(NUM2INT(rncid), NUM2INT(rmode), &old));
290
+ return INT2NUM(old);
291
+ }
292
+
293
+ /* Process-global HDF5 chunk cache parameters. */
294
+ static VALUE
295
+ rb_nc_set_chunk_cache (VALUE self, VALUE rsize, VALUE rnelems, VALUE rpreemption)
296
+ {
297
+ NC_CHECK(nc_set_chunk_cache(NUM2SIZET(rsize), NUM2SIZET(rnelems),
298
+ (float) NUM2DBL(rpreemption)));
299
+ return Qnil;
300
+ }
301
+
302
+ static VALUE
303
+ rb_nc_get_chunk_cache (VALUE self)
304
+ {
305
+ size_t size, nelems;
306
+ float pre;
307
+
308
+ NC_CHECK(nc_get_chunk_cache(&size, &nelems, &pre));
309
+ return rb_ary_new_from_args(3, SIZET2NUM(size), SIZET2NUM(nelems),
310
+ DBL2NUM((double) pre));
311
+ }
312
+
313
+ void
314
+ init_nc_file (void)
315
+ {
316
+ rb_define_module_function(mNetCDF, "nc_create", rb_nc_create, -1);
317
+ rb_define_module_function(mNetCDF, "nc_open", rb_nc_open, -1);
318
+ #ifdef HAVE_NC_OPEN_MEM
319
+ rb_define_module_function(mNetCDF, "nc_open_mem", rb_nc_open_mem, 3);
320
+ #endif
321
+ #ifdef HAVE_NC_CREATE_MEM
322
+ rb_define_module_function(mNetCDF, "nc_create_mem", rb_nc_create_mem, -1);
323
+ #endif
324
+ #ifdef HAVE_NC_CLOSE_MEMIO
325
+ rb_define_module_function(mNetCDF, "nc_close_memio", rb_nc_close_memio, 1);
326
+ #endif
327
+ rb_define_module_function(mNetCDF, "nc_close", rb_nc_close, 1);
328
+ rb_define_module_function(mNetCDF, "nc_abort", rb_nc_abort, 1);
329
+ rb_define_module_function(mNetCDF, "nc_sync", rb_nc_sync, 1);
330
+ rb_define_module_function(mNetCDF, "nc_redef", rb_nc_redef, 1);
331
+ rb_define_module_function(mNetCDF, "nc_enddef", rb_nc_enddef, 1);
332
+ rb_define_module_function(mNetCDF, "nc_inq", rb_nc_inq, 1);
333
+ rb_define_module_function(mNetCDF, "nc_inq_ndims", rb_nc_inq_ndims, 1);
334
+ rb_define_module_function(mNetCDF, "nc_inq_nvars", rb_nc_inq_nvars, 1);
335
+ rb_define_module_function(mNetCDF, "nc_inq_natts", rb_nc_inq_natts, 1);
336
+ rb_define_module_function(mNetCDF, "nc_inq_unlimdim", rb_nc_inq_unlimdim, 1);
337
+ #ifdef HAVE_NC_INQ_PATH
338
+ rb_define_module_function(mNetCDF, "nc_inq_path", rb_nc_inq_path, 1);
339
+ #endif
340
+ rb_define_module_function(mNetCDF, "nc_inq_format", rb_nc_inq_format, 1);
341
+ #ifdef HAVE_NC_INQ_FORMAT_EXTENDED
342
+ rb_define_module_function(mNetCDF, "nc_inq_format_extended", rb_nc_inq_format_extended, 1);
343
+ #endif
344
+ rb_define_module_function(mNetCDF, "nc_inq_libvers", rb_nc_inq_libvers, 0);
345
+ rb_define_module_function(mNetCDF, "nc_inq_type", rb_nc_inq_type, 2);
346
+ rb_define_module_function(mNetCDF, "nc_set_fill", rb_nc_set_fill, 2);
347
+ rb_define_module_function(mNetCDF, "nc_set_chunk_cache", rb_nc_set_chunk_cache, 3);
348
+ rb_define_module_function(mNetCDF, "nc_get_chunk_cache", rb_nc_get_chunk_cache, 0);
349
+ }
@@ -0,0 +1,171 @@
1
+ #include "internal.h"
2
+
3
+ static VALUE
4
+ rb_nc_def_grp (VALUE self, VALUE rparent, VALUE rname)
5
+ {
6
+ int grpid;
7
+
8
+ NC_CHECK(nc_def_grp(NUM2INT(rparent), StringValueCStr(rname), &grpid));
9
+ return INT2NUM(grpid);
10
+ }
11
+
12
+ static VALUE
13
+ rb_nc_rename_grp (VALUE self, VALUE rgrpid, VALUE rname)
14
+ {
15
+ NC_CHECK(nc_rename_grp(NUM2INT(rgrpid), StringValueCStr(rname)));
16
+ return Qnil;
17
+ }
18
+
19
+ static VALUE
20
+ rb_nc_inq_grps (VALUE self, VALUE rncid)
21
+ {
22
+ VALUE out;
23
+ int n, st, i;
24
+ int *ids;
25
+
26
+ NC_CHECK(nc_inq_grps(NUM2INT(rncid), &n, NULL));
27
+ ids = ALLOC_N(int, n > 0 ? n : 1);
28
+ st = nc_inq_grps(NUM2INT(rncid), NULL, ids);
29
+ if ( st != NC_NOERR ) {
30
+ xfree(ids);
31
+ nc_raise(st);
32
+ }
33
+ out = rb_ary_new_capa(n);
34
+ for (i=0; i<n; i++) {
35
+ rb_ary_push(out, INT2NUM(ids[i]));
36
+ }
37
+ xfree(ids);
38
+ return out;
39
+ }
40
+
41
+ static VALUE
42
+ rb_nc_inq_grpname (VALUE self, VALUE rncid)
43
+ {
44
+ char name[NC_MAX_NAME + 1];
45
+
46
+ NC_CHECK(nc_inq_grpname(NUM2INT(rncid), name));
47
+ return rb_utf8_str_new_cstr(name);
48
+ }
49
+
50
+ static VALUE
51
+ rb_nc_inq_grpname_full (VALUE self, VALUE rncid)
52
+ {
53
+ VALUE out;
54
+ size_t len;
55
+
56
+ NC_CHECK(nc_inq_grpname_len(NUM2INT(rncid), &len));
57
+ out = rb_str_buf_new((long) len);
58
+ rb_str_set_len(out, (long) len);
59
+ rb_enc_associate(out, rb_utf8_encoding());
60
+ NC_CHECK(nc_inq_grpname_full(NUM2INT(rncid), NULL, RSTRING_PTR(out)));
61
+ return out;
62
+ }
63
+
64
+ /* Returns parent ncid, or nil for the root group. */
65
+ static VALUE
66
+ rb_nc_inq_grp_parent (VALUE self, VALUE rncid)
67
+ {
68
+ int parent, st;
69
+
70
+ st = nc_inq_grp_parent(NUM2INT(rncid), &parent);
71
+ if ( st == NC_ENOGRP ) {
72
+ return Qnil;
73
+ }
74
+ if ( st != NC_NOERR ) {
75
+ nc_raise(st);
76
+ }
77
+ return INT2NUM(parent);
78
+ }
79
+
80
+ static VALUE
81
+ rb_nc_inq_ncid (VALUE self, VALUE rncid, VALUE rname)
82
+ {
83
+ int grpid, st;
84
+
85
+ st = nc_inq_ncid(NUM2INT(rncid), StringValueCStr(rname), &grpid);
86
+ if ( st == NC_ENOGRP ) {
87
+ return Qnil;
88
+ }
89
+ if ( st != NC_NOERR ) {
90
+ nc_raise(st);
91
+ }
92
+ return INT2NUM(grpid);
93
+ }
94
+
95
+ static VALUE
96
+ rb_nc_inq_grp_full_ncid (VALUE self, VALUE rncid, VALUE rfull_name)
97
+ {
98
+ int grpid, st;
99
+
100
+ st = nc_inq_grp_full_ncid(NUM2INT(rncid), StringValueCStr(rfull_name), &grpid);
101
+ if ( st == NC_ENOGRP ) {
102
+ return Qnil;
103
+ }
104
+ if ( st != NC_NOERR ) {
105
+ nc_raise(st);
106
+ }
107
+ return INT2NUM(grpid);
108
+ }
109
+
110
+ static VALUE
111
+ rb_nc_inq_dimids (int argc, VALUE *argv, VALUE self)
112
+ {
113
+ VALUE rncid, rinclude_parents, out;
114
+ int ncid, include_parents, n, st, i;
115
+ int *ids;
116
+
117
+ rb_scan_args(argc, argv, "11", &rncid, &rinclude_parents);
118
+ ncid = NUM2INT(rncid);
119
+ include_parents = RTEST(rinclude_parents) ? 1 : 0;
120
+
121
+ NC_CHECK(nc_inq_dimids(ncid, &n, NULL, include_parents));
122
+ ids = ALLOC_N(int, n > 0 ? n : 1);
123
+ st = nc_inq_dimids(ncid, NULL, ids, include_parents);
124
+ if ( st != NC_NOERR ) {
125
+ xfree(ids);
126
+ nc_raise(st);
127
+ }
128
+ out = rb_ary_new_capa(n);
129
+ for (i=0; i<n; i++) {
130
+ rb_ary_push(out, INT2NUM(ids[i]));
131
+ }
132
+ xfree(ids);
133
+ return out;
134
+ }
135
+
136
+ static VALUE
137
+ rb_nc_inq_varids (VALUE self, VALUE rncid)
138
+ {
139
+ VALUE out;
140
+ int n, st, i;
141
+ int *ids;
142
+
143
+ NC_CHECK(nc_inq_varids(NUM2INT(rncid), &n, NULL));
144
+ ids = ALLOC_N(int, n > 0 ? n : 1);
145
+ st = nc_inq_varids(NUM2INT(rncid), NULL, ids);
146
+ if ( st != NC_NOERR ) {
147
+ xfree(ids);
148
+ nc_raise(st);
149
+ }
150
+ out = rb_ary_new_capa(n);
151
+ for (i=0; i<n; i++) {
152
+ rb_ary_push(out, INT2NUM(ids[i]));
153
+ }
154
+ xfree(ids);
155
+ return out;
156
+ }
157
+
158
+ void
159
+ init_nc_group (void)
160
+ {
161
+ rb_define_module_function(mNetCDF, "nc_def_grp", rb_nc_def_grp, 2);
162
+ rb_define_module_function(mNetCDF, "nc_rename_grp", rb_nc_rename_grp, 2);
163
+ rb_define_module_function(mNetCDF, "nc_inq_grps", rb_nc_inq_grps, 1);
164
+ rb_define_module_function(mNetCDF, "nc_inq_grpname", rb_nc_inq_grpname, 1);
165
+ rb_define_module_function(mNetCDF, "nc_inq_grpname_full", rb_nc_inq_grpname_full, 1);
166
+ rb_define_module_function(mNetCDF, "nc_inq_grp_parent", rb_nc_inq_grp_parent, 1);
167
+ rb_define_module_function(mNetCDF, "nc_inq_ncid", rb_nc_inq_ncid, 2);
168
+ rb_define_module_function(mNetCDF, "nc_inq_grp_full_ncid", rb_nc_inq_grp_full_ncid, 2);
169
+ rb_define_module_function(mNetCDF, "nc_inq_dimids", rb_nc_inq_dimids, -1);
170
+ rb_define_module_function(mNetCDF, "nc_inq_varids", rb_nc_inq_varids, 1);
171
+ }