1/* This is part of the netCDF package.
2   Copyright 2006 University Corporation for Atmospheric Research/Unidata.
3   See COPYRIGHT file for conditions of use.
4
5   This is a very simple example which writes a netCDF file with
6   Unicode names encoded with UTF-8. It is the NETCDF3 equivalent
7   of tst_unicode.c
8
9   $Id: tst_utf8.c,v 1.14 2008/10/20 01:48:09 ed Exp $
10*/
11
12#include <config.h>
13#include <stdlib.h>
14#include <nc_tests.h>
15#include "err_macros.h"
16#include <netcdf.h>
17#include <string.h>
18
19/* The data file we will create. */
20#define FILE_NAME "tst_utf8.nc"
21#define NDIMS 1
22#define NX 18
23#define ENUM_VALUE 2
24
25/* (unnormalized) UTF-8 encoding for Unicode 8-character "Hello" in Greek */
26char name_utf8[] = "\xCE\x9A\xCE\xB1\xCE\xBB\xCE\xB7\xCE\xBC\xE1\xBD\xB3\xCF\x81\xCE\xB1";
27
28/* NFC normalized UTF-8 for Unicode 8-character "Hello" in Greek */
29char norm_utf8[] = "\xCE\x9A\xCE\xB1\xCE\xBB\xCE\xB7\xCE\xBC\xCE\xAD\xCF\x81\xCE\xB1";
30
31/* This is the struct for the compound type. */
32struct comp {
33      int i;
34};
35
36/* Given an ncid, check the file to make sure it has all the objects I
37 * expect. */
38int
39check_nc4_file(int ncid)
40{
41   int variddimidattnumgrpidgrpid2grpid3numgrps;
42   int numtypesenum_typeidcomp_typeid;
43   int class_in;
44   size_t att_lensize_innum_memnfields_in;
45   nc_type att_typebase_type_in;
46   char name_in[NC_MAX_NAME + 1], strings_in[NC_MAX_NAME + 1], value;
47
48   /* Check the group. */
49   if (nc_inq_grps(ncid, &numgrps, &grpid)) ERR;
50   if (numgrps != 1) ERR;
51   name_in[0] = 0;
52   if (nc_inq_grpname(grpidname_in)) ERR;
53   if (strncmp(norm_utf8name_in, sizeof(norm_utf8))) ERR;
54
55   /* Check the variable. */
56   if (nc_inq_varid(grpidname_utf8, &varid)) ERR;
57   if (nc_inq_varname(grpidvaridname_in)) ERR;
58   if (strncmp(norm_utf8name_in, sizeof(norm_utf8))) ERR;
59   if (nc_inq_varid(grpidnorm_utf8, &varid)) ERR;
60   name_in[0] = 0;
61   if (nc_inq_varname(grpidvaridname_in)) ERR;
62   if (strncmp(norm_utf8name_in, sizeof(norm_utf8))) ERR;
63   if (nc_get_var(grpidvaridstrings_in)) ERR;
64   if (strncmp(name_utf8strings_in, sizeof(name_utf8))) ERR;
65   strings_in[0] = '\0'; /* Reset my string buffer. */
66
67   /* Check the dimension. */
68   if (nc_inq_dimid(grpidname_utf8, &dimid)) ERR;
69   if (nc_inq_dimname(grpiddimidname_in)) ERR;
70   if (strncmp(norm_utf8name_in, sizeof(norm_utf8))) ERR;
71   if (nc_inq_dimid(grpidnorm_utf8, &dimid)) ERR;
72   if (nc_inq_dimname(grpiddimidname_in)) ERR;
73   if (strncmp(norm_utf8name_in, sizeof(norm_utf8))) ERR;
74
75   /* Check the attribute.  We don't normalize data or attribute
76    * values, so get exactly what was put for the value, but
77    * normalized values for names. */
78   if (nc_inq_attid(grpidvaridnorm_utf8, &attnum)) ERR;
79   if (attnumERR;
80   attnum = 99; /* Reset. */
81   if (nc_inq_attid(grpidvaridname_utf8, &attnum)) ERR;
82   if (attnumERR;
83   if (nc_inq_att(grpidvaridnorm_utf8, &att_type, &att_len)) ERR;
84   if (att_type != NC_CHAR || att_len != sizeof(name_utf8)) ERR;
85   if (nc_get_att_text(grpidvaridnorm_utf8strings_in)) ERR;
86   if (strncmp(name_utf8strings_in, sizeof(name_utf8))) ERR;
87
88   /* Check the enum type. */
89   if (nc_inq_grps(grpid, &numgrps, &grpid2)) ERR;
90   if (numgrps != 1) ERR;
91   if (nc_inq_typeids(grpid2, &numtypes, &enum_typeid)) ERR;
92   if (numtypes != 1) ERR;
93   if (nc_inq_user_type(grpid2enum_typeidname_in, &size_in, &base_type_in,
94        &nfields_in, &class_in)) ERR;
95   if (strncmp(norm_utf8name_in, strlen(norm_utf8)) || size_in != 1 ||
96       base_type_in != NC_BYTE || nfields_in != 1 || class_in != NC_ENUMERR;
97   name_in[0] = size_in = base_type_in = 0;
98   if (nc_inq_enum(grpid2enum_typeidname_in, &base_type_in, &size_in, &num_mem)) ERR;
99   if (strncmp(norm_utf8name_in, strlen(norm_utf8)) || size_in != 1 ||
100       base_type_in != NC_BYTE || num_mem != 1) ERR;
101   if (nc_inq_enum_member(grpid2enum_typeid, 0, name_in, &value)) ERR;
102   if (strncmp(norm_utf8name_in, sizeof(norm_utf8)) || value != ENUM_VALUEERR;
103
104   /* Check the compound type. */
105   if (nc_inq_grps(grpid2, &numgrps, &grpid3)) ERR;
106   if (numgrps != 1) ERR;
107   if (nc_inq_typeids(grpid3, &numtypes, &comp_typeid)) ERR;
108   if (numtypes != 1) ERR;
109   name_in[0] = 0;
110   if (nc_inq_user_type(grpid3comp_typeidname_in, &size_in, &base_type_in,
111 &nfields_in, &class_in)) ERR;
112   if (strncmp(norm_utf8name_in, sizeof(norm_utf8)) || size_in != sizeof(struct comp) ||
113       base_type_in != NC_NAT || nfields_in != 1 || class_in != NC_COMPOUNDERR;
114   size_in = nfields_in = 999;
115   if (nc_inq_compound(grpid3comp_typeidname_in, &size_in, &nfields_in)) ERR;
116   if (strncmp(norm_utf8name_in, sizeof(norm_utf8)) || size_in != sizeof(struct comp) ||
117       nfields_in != 1) ERR;
118   name_in[0] = 0;
119   if (nc_inq_compound_fieldname(grpid3comp_typeid, 0, name_in)) ERR;
120   if (strncmp(norm_utf8name_in, sizeof(norm_utf8))) ERR;
121   return NC_NOERR;
122}
123
124/* Given an ncid, check the file to make sure it has all the objects I
125 * expect. */
126int
127check_classic_file(int ncid)
128{
129   int variddimidattnum;
130   size_t att_len;
131   nc_type att_type;
132   char name_in[sizeof(name_utf8) + 1], strings_in[sizeof(name_utf8) + 1];
133
134   /* Check the variable. */
135   if (nc_inq_varid(ncidname_utf8, &varid)) ERR;
136   if (nc_inq_varname(ncidvaridname_in)) ERR;
137   if (strncmp(norm_utf8name_in, sizeof(norm_utf8))) ERR;
138   if (nc_inq_varid(ncidnorm_utf8, &varid)) ERR;
139   name_in[0] = 0;
140   if (nc_inq_varname(ncidvaridname_in)) ERR;
141   if (strncmp(norm_utf8name_in, sizeof(norm_utf8))) ERR;
142   if (nc_get_var_text(ncidvaridstrings_in)) ERR;
143   if (strncmp(name_utf8strings_in, sizeof(name_utf8))) ERR;
144   strings_in[0] = '\0'; /* Reset my string buffer. */
145
146   /* Check the dimension. */
147   if (nc_inq_dimid(ncidname_utf8, &dimid)) ERR;
148   if (nc_inq_dimname(nciddimidname_in)) ERR;
149   if (strncmp(norm_utf8name_in, sizeof(norm_utf8))) ERR;
150   if (nc_inq_dimid(ncidnorm_utf8, &dimid)) ERR;
151   if (nc_inq_dimname(nciddimidname_in)) ERR;
152   if (strncmp(norm_utf8name_in, sizeof(norm_utf8))) ERR;
153
154   /* Check the attribute.  We don't normalize data or attribute
155    * values, so get exactly what was put for the value, but
156    * normalized values for names. */
157   if (nc_inq_attid(ncidvaridnorm_utf8, &attnum)) ERR;
158   if (attnumERR;
159   attnum = 99; /* Reset. */
160   if (nc_inq_attid(ncidvaridname_utf8, &attnum)) ERR;
161   if (attnumERR;
162   if (nc_inq_att(ncidvaridnorm_utf8, &att_type, &att_len)) ERR;
163   if (att_type != NC_CHAR || att_len != sizeof(name_utf8)) ERR;
164   if (nc_get_att_text(ncidvaridnorm_utf8strings_in)) ERR;
165   if (strncmp(name_utf8strings_in, sizeof(name_utf8))) ERR;
166   return NC_NOERR;
167}
168
169int
170main(int argc, char **argv)
171{
172   printf("\n*** Testing UTF-8 names.\n");
173   printf("*** creating UTF-8 names in classic model netcdf files...");
174   {
175      int ncidvariddimids[NDIMS];
176      int f;
177
178      for (f = NC_FORMAT_CLASSICf < NC_FORMAT_NETCDF4_CLASSICf++)
179      {
180  if (nc_set_default_format(fNULL)) ERR;
181  if (nc_create(FILE_NAMENC_CLOBBER, &ncid)) ERR;
182
183  /* Define various netcdf objects with a Unicode UTF-8 encoded name
184   * that must be normalized. Where possible, also use the utf8
185   * string as the value. The name will be normalized, but not the
186   * value. */
187  if (nc_def_dim(ncidname_utf8NX, &dimids[0])) ERR;
188  if (nc_def_var(ncidname_utf8NC_CHARNDIMSdimids, &varid)) ERR;
189  if (nc_put_att_text(ncidvaridname_utf8, sizeof(name_utf8), name_utf8)) ERR;
190
191  if (nc_enddef(ncid)) ERR;
192
193  /* Write var data. */
194  if (nc_put_var_text(ncidvaridname_utf8)) ERR;
195
196  /* Check the file. */
197  check_classic_file(ncid);
198
199  if (nc_close(ncid)) ERR;
200
201  /* Reopen the file and check again. */
202  if (nc_open(FILE_NAMENC_NOWRITE, &ncid)) ERR;
203  check_classic_file(ncid);
204  if (nc_close(ncid)) ERR;
205      } /* next format */
206   }
207   SUMMARIZE_ERR;
208
209#define DIM1_NAME "d1"
210#define VAR1_NAME "v1"
211#define ATT1_NAME "a1"
212
213   printf("*** renaming to UTF-8 names in classic model netcdf files...");
214   {
215      int ncidvariddimids[NDIMS];
216      int f;
217
218      for (f = NC_FORMAT_CLASSICf < NC_FORMAT_NETCDF4_CLASSICf++)
219      {
220  if (nc_set_default_format(fNULL)) ERR;
221  if (nc_create(FILE_NAMENC_CLOBBER, &ncid)) ERR;
222
223  /* Create objects. */
224  if (nc_def_dim(ncidDIM1_NAMENX, &dimids[0])) ERR;
225  if (nc_rename_dim(ncid, 0, name_utf8)) ERR;
226   if (nc_def_var(ncidname_utf8NC_CHARNDIMSdimids, &varid)) ERR;
227   if (nc_put_att_text(ncidvaridATT1_NAME, sizeof(name_utf8), name_utf8)) ERR;
228   if (nc_rename_att(ncid, 0, ATT1_NAMEname_utf8)) ERR;
229
230  if (nc_enddef(ncid)) ERR;
231
232  /* Write var data. */
233  if (nc_put_var_text(ncidvaridname_utf8)) ERR;
234
235  /* Check the file. */
236  check_classic_file(ncid);
237
238  if (nc_close(ncid)) ERR;
239
240  /* Reopen the file and check again. */
241  if (nc_open(FILE_NAMENC_NOWRITE, &ncid)) ERR;
242  check_classic_file(ncid);
243  if (nc_close(ncid)) ERR;
244      } /* next format */
245   }
246   SUMMARIZE_ERR;
247
248   printf("*** creating UTF-8 names in netcdf-4 file...");
249   {
250      int ncidvaridgrpidcomp_typeidenum_typeidgrpid2grpid3;
251      int dimids[NDIMS];
252      char my_int = ENUM_VALUE;
253
254      if (nc_create(FILE_NAMENC_NETCDF4 | NC_CLOBBER, &ncid)) ERR;
255
256      /* Define various netcdf objects with a Unicode UTF-8 encoded name
257       * that must be normalized. Where possible, also use the utf8
258       * string as the value. The name will be normalized, but not the
259       * value. */
260      if (nc_def_grp(ncidname_utf8, &grpid)) ERR;
261      if (nc_def_dim(grpidname_utf8NX, &dimids[0])) ERR;
262      if (nc_def_var(grpidname_utf8NC_CHARNDIMSdimids, &varid)) ERR;
263      if (nc_put_att_text(grpidvaridname_utf8, sizeof(name_utf8), name_utf8)) ERR;
264
265      if (nc_def_grp(grpid, "tmp", &grpid2)) ERR;
266      if (nc_def_enum(grpid2NC_BYTEname_utf8, &enum_typeid)) ERR;
267      if (nc_insert_enum(grpid2enum_typeidname_utf8, &my_int)) ERR;
268
269      if (nc_def_grp(grpid2, "tmp", &grpid3)) ERR;
270      if (nc_def_compound(grpid3, sizeof(struct comp), name_utf8, &comp_typeid)) ERR;
271      if (nc_insert_compound(grpid3comp_typeidname_utf8offsetof(struct compi), NC_INT)) ERR;
272
273      /* Write var data. */
274      if (nc_put_var_text(grpidvaridname_utf8)) ERR;
275
276      /* Check the file. */
277      check_nc4_file(ncid);
278
279      if (nc_close(ncid)) ERR;
280
281      /* Reopen the file and check again. */
282      if (nc_open(FILE_NAMENC_NOWRITE, &ncid)) ERR;
283      check_nc4_file(ncid);
284      if (nc_close(ncid)) ERR;
285   }
286
287   SUMMARIZE_ERR;
288   FINAL_RESULTS;
289}


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed