Coverage Report

Created: 2026-08-22 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/netcdf-c/libnczarr/zarr.c
Line
Count
Source
1
/*********************************************************************
2
 *   Copyright 2018, UCAR/Unidata
3
 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4
 *********************************************************************/
5
6
#include "zincludes.h"
7
#include <stddef.h>
8
9
/**************************************************/
10
/* Forwards */
11
12
static int applycontrols(NCZ_FILE_INFO_T* zinfo);
13
14
/***************************************************/
15
/* API */
16
17
/**
18
@internal Create the topmost dataset object and setup up
19
          NCZ_FILE_INFO_T state.
20
@param zinfo - [in] the internal state
21
@return NC_NOERR
22
@author Dennis Heimbigner
23
*/
24
25
int
26
ncz_create_dataset(NC_FILE_INFO_T* file, NC_GRP_INFO_T* root, NClist* controls)
27
0
{
28
0
    int stat = NC_NOERR;
29
0
    NCZ_FILE_INFO_T* zinfo = NULL;
30
0
    NCZ_GRP_INFO_T* zgrp = NULL;
31
0
    NCURI* uri = NULL;
32
0
    NC* nc = NULL;
33
0
    NCjson* json = NULL;
34
0
    char* key = NULL;
35
36
0
    ZTRACE(3,"file=%s root=%s controls=%s",file->hdr.name,root->hdr.name,(controls?nczprint_envv(controls):"null"));
37
38
0
    nc = (NC*)file->controller;
39
40
    /* Add struct to hold NCZ-specific file metadata. */
41
0
    if (!(zinfo = calloc(1, sizeof(NCZ_FILE_INFO_T))))
42
0
        {stat = NC_ENOMEM; goto done;}
43
0
    file->format_file_info = zinfo;
44
0
    zinfo->common.file = file;
45
46
    /* Add struct to hold NCZ-specific group info. */
47
0
    if (!(zgrp = calloc(1, sizeof(NCZ_GRP_INFO_T))))
48
0
        {stat = NC_ENOMEM; goto done;}
49
0
    root->format_grp_info = zgrp;
50
0
    zgrp->common.file = file;
51
52
    /* Fill in NCZ_FILE_INFO_T */
53
0
    zinfo->creating = 1;
54
0
    zinfo->common.file = file;
55
0
    zinfo->native_endianness = (NC_isLittleEndian() ? NC_ENDIAN_LITTLE : NC_ENDIAN_BIG);
56
0
    if((zinfo->controllist=nclistclone(controls,1)) == NULL)
57
0
  {stat = NC_ENOMEM; goto done;}
58
59
    /* fill in some of the zinfo and zroot fields */
60
0
    zinfo->format.zarr = ZARRFORMAT2;
61
0
    zinfo->format.nczarr = NCZARRFORMAT2;
62
63
0
    zinfo->default_maxstrlen = NCZ_MAXSTR_DEFAULT;
64
65
    /* Apply client controls */
66
0
    if((stat = applycontrols(zinfo))) goto done;
67
68
    /* Load auth info from rc file */
69
0
    if((stat = ncuriparse(nc->path,&uri))) goto done;
70
0
    if(uri) {
71
0
  if((stat = NC_authsetup(&zinfo->auth, uri)))
72
0
      goto done;
73
0
    }
74
75
    /* initialize map handle*/
76
0
    if((stat = NCZ_get_map(file,uri,nc->mode,zinfo->controls.flags,NULL,&zinfo->map))){
77
0
        goto done;
78
0
    }
79
80
0
    if((stat = NCZMD_set_metadata_handler(zinfo))){
81
0
        goto done;
82
0
    }
83
84
0
done:
85
0
    ncurifree(uri);
86
0
    NCJreclaim(json);
87
0
    nullfree(key);
88
0
    return ZUNTRACE(stat);
89
0
}
90
91
/**
92
@internal Open the topmost dataset object.
93
@param file - [in] the file struct
94
@param controls - [in] the fragment list in envv form from uri
95
@return NC_NOERR
96
@author Dennis Heimbigner
97
*/
98
99
int
100
ncz_open_dataset(NC_FILE_INFO_T* file, NClist* controls)
101
0
{
102
0
    int stat = NC_NOERR;
103
0
    NC* nc = NULL;
104
0
    NC_GRP_INFO_T* root = NULL;
105
0
    NCURI* uri = NULL;
106
0
    void* content = NULL;
107
0
    NCjson* json = NULL;
108
0
    NCZ_FILE_INFO_T* zinfo = NULL;
109
0
    int mode;
110
0
    NClist* modeargs = NULL;
111
0
    char* nczarr_version = NULL;
112
0
    char* zarr_format = NULL;
113
114
0
    ZTRACE(3,"file=%s controls=%s",file->hdr.name,(controls?nczprint_envv(controls):"null"));
115
116
    /* Extract info reachable via file */
117
0
    nc = (NC*)file->controller;
118
0
    mode = nc->mode;
119
120
0
    root = file->root_grp;
121
0
    assert(root != NULL && root->hdr.sort == NCGRP);
122
123
    /* Add struct to hold NCZ-specific file metadata. */
124
0
    if (!(file->format_file_info = calloc(1, sizeof(NCZ_FILE_INFO_T))))
125
0
        {stat = NC_ENOMEM; goto done;}
126
0
    zinfo = file->format_file_info;
127
128
    /* Fill in NCZ_FILE_INFO_T */
129
0
    zinfo->creating = 0;
130
0
    zinfo->common.file = file;
131
0
    zinfo->native_endianness = (NC_isLittleEndian() ? NC_ENDIAN_LITTLE : NC_ENDIAN_BIG);
132
0
    if((zinfo->controllist=nclistclone(controls,1)) == NULL)
133
0
  {stat = NC_ENOMEM; goto done;}
134
0
    zinfo->default_maxstrlen = NCZ_MAXSTR_DEFAULT;
135
136
    /* Add struct to hold NCZ-specific group info. */
137
0
    if (!(root->format_grp_info = calloc(1, sizeof(NCZ_GRP_INFO_T))))
138
0
        {stat = NC_ENOMEM; goto done;}
139
0
    ((NCZ_GRP_INFO_T*)root->format_grp_info)->common.file = file;
140
141
    /* Apply client controls */
142
0
    if((stat = applycontrols(zinfo))) goto done;
143
144
    /* Load auth info from rc file */
145
0
    if((stat = ncuriparse(nc->path,&uri))) goto done;
146
0
    if(uri) {
147
0
  if((stat = NC_authsetup(&zinfo->auth, uri)))
148
0
      goto done;
149
0
    }
150
151
    /* initialize map handle*/
152
0
    if((stat = NCZ_get_map(file, uri, mode, zinfo->controls.flags,NULL,&zinfo->map))){
153
0
      goto done;
154
0
    }
155
156
    /* Determine zarr format of existing dataset */
157
0
    if((stat = NCZ_infer_zarr_format(file))) {
158
0
        goto done;
159
0
    }
160
161
0
    if((stat = NCZMD_set_metadata_handler(zinfo))) {
162
0
        goto done;
163
0
    }
164
165
0
    if((stat = NCZ_infer_nczarr_format(file))) {
166
0
        goto done;
167
0
    }
168
169
0
done:
170
0
    nullfree(zarr_format);
171
0
    nullfree(nczarr_version);
172
0
    ncurifree(uri);
173
0
    nclistfreeall(modeargs);
174
0
    if(json) NCJreclaim(json);
175
0
    nullfree(content);
176
0
    return ZUNTRACE(stat);
177
0
}
178
179
/**
180
 * @internal Determine whether file is netCDF-4.
181
 *
182
 * For libzarr, this is always true.
183
 *
184
 * @param h5 Pointer to HDF5 file info struct.
185
 *
186
 * @returns NC_NOERR No error.
187
 * @author Dennis Heimbigner.
188
 */
189
int
190
NCZ_isnetcdf4(struct NC_FILE_INFO* h5)
191
0
{
192
0
    int isnc4 = 1;
193
0
    NC_UNUSED(h5);
194
0
    return isnc4;
195
0
}
196
197
/**
198
 * @internal Determine version info
199
 *
200
 * For libzarr, this is not well defined
201
 *
202
 * @param majorp Pointer to major version number
203
 * @param minorp Pointer to minor version number
204
 * @param releasep Pointer to release version number
205
 *
206
 * @returns NC_NOERR No error.
207
 * @author Dennis Heimbigner.
208
 */
209
int
210
NCZ_get_libversion(unsigned long* majorp, unsigned long* minorp,unsigned long* releasep)
211
1
{
212
1
    unsigned long m0,m1,m2;
213
1
    sscanf(NCZARR_PACKAGE_VERSION,"%lu.%lu.%lu",&m0,&m1,&m2);
214
1
    if(majorp) *majorp = m0;
215
1
    if(minorp) *minorp = m1;
216
1
    if(releasep) *releasep = m2;
217
1
    return NC_NOERR;
218
1
}
219
220
/**
221
 * @internal Determine "superblock" number.
222
 *
223
 * For libzarr, use the value of the major part of the nczarr version.
224
 *
225
 * @param superblocp Pointer to place to return superblock.
226
 * use the nczarr format version major as the superblock number.
227
 *
228
 * @returns NC_NOERR No error.
229
 * @author Dennis Heimbigner.
230
 */
231
int
232
NCZ_get_superblock(NC_FILE_INFO_T* file, int* superblockp)
233
0
{
234
0
    NCZ_FILE_INFO_T* zinfo = file->format_file_info;
235
0
    if(superblockp) *superblockp = zinfo->format.nczarr;
236
0
    return NC_NOERR;
237
0
}
238
239
/**************************************************/
240
/* Utilities */
241
242
static const char*
243
controllookup(NClist* controls, const char* key)
244
0
{
245
0
    size_t i;
246
0
    for(i=0;i<nclistlength(controls);i+=2) {
247
0
        const char* p = (char*)nclistget(controls,i);
248
0
  if(strcasecmp(key,p)==0) {
249
0
      return (const char*)nclistget(controls,i+1);
250
0
  }
251
0
    }
252
0
    return NULL;
253
0
}
254
255
256
static int
257
applycontrols(NCZ_FILE_INFO_T* zinfo)
258
0
{
259
0
    size_t i;
260
0
    int stat = NC_NOERR;
261
0
    const char* value = NULL;
262
0
    NClist* modelist = nclistnew();
263
0
    size64_t noflags = 0; /* track non-default negative flags */
264
265
0
    if((value = controllookup(zinfo->controllist,"mode")) != NULL) {
266
0
  if((stat = NCZ_comma_parse(value,modelist))) goto done;
267
0
    }
268
    /* Process the modelist first */
269
0
    zinfo->controls.mapimpl = NCZM_DEFAULT;
270
0
    zinfo->controls.flags |= FLAG_XARRAYDIMS; /* Always support XArray convention where possible */
271
0
    zinfo->controls.flags |= (NCZARR_CONSOLIDATED_DEFAULT ? FLAG_CONSOLIDATED : 0);
272
0
    for(i=0;i<nclistlength(modelist);i++) {
273
0
        const char* p = nclistget(modelist,i);
274
0
  if(strcasecmp(p,PUREZARRCONTROL)==0)
275
0
      zinfo->controls.flags |= (FLAG_PUREZARR);
276
0
  else if(strcasecmp(p,XARRAYCONTROL)==0)
277
0
      zinfo->controls.flags |= FLAG_PUREZARR;
278
0
  else if(strcasecmp(p,NOXARRAYCONTROL)==0)
279
0
      noflags |= FLAG_XARRAYDIMS;
280
0
  else if(strcasecmp(p,"zip")==0) zinfo->controls.mapimpl = NCZM_ZIP;
281
0
  else if(strcasecmp(p,"file")==0) zinfo->controls.mapimpl = NCZM_FILE;
282
0
  else if(strcasecmp(p,"s3")==0) zinfo->controls.mapimpl = NCZM_S3;
283
0
  else if(strcasecmp(p,"consolidated") == 0)
284
0
          zinfo->controls.flags |= FLAG_CONSOLIDATED;
285
0
    }
286
    /* Apply negative controls by turning off negative flags */
287
    /* This is necessary to avoid order dependence of mode flags when both positive and negative flags are defined */
288
0
    zinfo->controls.flags &= (~noflags);
289
290
    /* Process other controls */
291
0
    if((value = controllookup(zinfo->controllist,"log")) != NULL) {
292
0
  zinfo->controls.flags |= FLAG_LOGGING;
293
0
        ncsetloglevel(NCLOGNOTE);
294
0
    }
295
0
    if((value = controllookup(zinfo->controllist,"show")) != NULL) {
296
0
  if(strcasecmp(value,"fetch")==0)
297
0
      zinfo->controls.flags |= FLAG_SHOWFETCH;
298
0
    }
299
0
done:
300
0
    nclistfreeall(modelist);
301
0
    return stat;
302
0
}