1 #ifdef HAVE_CONFIG_H
2 #  include "config.h"
3 #endif
4 
5 #include <math.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 
9 #include "cdi.h"
10 
11 static void
12 printAtts(int vlistID);
13 
main(int argc,const char ** argv)14 int main(int argc, const char **argv)
15 {
16   // todo: handle optional arguments here to increase test coverage
17   const char *fname = (argc > 1) ? argv[1] : "test.nc";
18 
19   int countMissingValues = 1;
20 
21   int streamID = streamOpenRead(fname);
22   if (streamID < 0)
23     {
24       fprintf(stderr, "Open failed for file %s: %s\n",
25               fname, cdiStringError(streamID));
26       return EXIT_FAILURE;
27     }
28   int vlistID = streamInqVlist(streamID);
29   size_t nVars = (size_t)vlistNvars(vlistID);
30 
31   double *buf = NULL;
32   size_t bufSize = 0;
33   size_t allNmissSum = 0;
34 
35   printAtts(vlistID);
36 
37   for (int tsID = 0; streamInqTimestep(streamID, tsID); ++tsID)
38     {
39       for (size_t varID = 0; varID < nVars; ++varID)
40         {
41           size_t memSize = (size_t)vlistInqVarSize(vlistID, (int)varID)
42             * sizeof (double);
43           SizeType nmiss;
44           if (memSize > bufSize)
45             {
46               double *temp = (double *)realloc(buf, memSize);
47               if (!temp)
48                 {
49                   perror("read buffer reallocation failed");
50                   return EXIT_FAILURE;
51                 }
52               buf = temp;
53             }
54           streamReadVar(streamID, (int)varID, buf, &nmiss);
55           allNmissSum += nmiss;
56         }
57     }
58   if (countMissingValues)
59     printf("missing values count = %zu\n", allNmissSum);
60   streamClose(streamID);
61   return EXIT_SUCCESS;
62 }
63 
64 static void
printAtts(int vlistID)65 printAtts(int vlistID)
66 {
67   size_t nVars = (size_t)vlistNvars(vlistID);
68   static const char globDesc[] = "global",
69     varDescPrefix[] = "variable ";
70   size_t digitsPerInt = 9;
71   size_t bufSize = digitsPerInt + sizeof (varDescPrefix);
72   void *restrict buf = malloc(bufSize);
73   if (!buf)
74     {
75       perror("attribute buffer resize failed");
76       exit(EXIT_FAILURE);
77     }
78   for (size_t varIdx = 0; varIdx <= nVars; ++varIdx)
79     {
80       int nAtts, attType, attLen;
81       char attName[CDI_MAX_NAME + 1];
82       int varID = (int)varIdx - 1;
83       cdiInqNatts(vlistID, varID, &nAtts);
84       for (size_t attIdx = 0; attIdx < (size_t)nAtts; attIdx++ )
85         {
86           int rc = cdiInqAtt(vlistID, varID, (int)attIdx,
87                              attName, &attType, &attLen);
88           {
89             const char *varDesc = varIdx > 0
90               ? (sprintf((char *)buf, "%s%d", varDescPrefix,
91                          vlistInqVarCode(vlistID, varID)), (char *)buf)
92               : globDesc;
93             printf("%s attribute \"%s\", value: ",
94                    varDesc, attName);
95           }
96           if (attLen < 0)
97             {
98             puts("error retrieving value");
99             continue;
100             }
101           size_t elemSize = 0;
102           switch (attType)
103             {
104             case CDI_DATATYPE_TXT:
105               elemSize = 1;
106               break;
107             case CDI_DATATYPE_FLT:
108               elemSize = sizeof (double);
109               break;
110             case CDI_DATATYPE_INT:
111               elemSize = sizeof (int);
112               break;
113             }
114 
115           size_t attSize = elemSize * ((size_t)attLen + 1);
116           if (attSize > bufSize)
117             {
118               if (!(buf = realloc(buf, attSize)))
119                 {
120                   perror("attribute buffer resize failed");
121                   exit(EXIT_FAILURE);
122                 }
123             }
124 
125           switch (attType)
126             {
127             case CDI_DATATYPE_TXT:
128               rc = cdiInqAttTxt(vlistID, (int)varID, attName,
129                                 attLen, (char *)buf);
130               if (rc == CDI_NOERR)
131                 printf("\"%.*s\"", attLen, (char *)buf);
132               break;
133             case CDI_DATATYPE_FLT:
134               rc = cdiInqAttFlt(vlistID, (int)varID, attName,
135                                 attLen + 1, (double *)buf);
136               if (rc == CDI_NOERR && attLen)
137                 {
138                   const double *restrict dp = (const double*)buf;
139                   printf("%10g", dp[0]);
140                   for (size_t i = 1; i < (size_t)attLen; ++i)
141                     printf(", %10g", dp[i]);
142                 }
143               break;
144             case CDI_DATATYPE_INT:
145               rc = cdiInqAttInt(vlistID, (int)varID, attName,
146                                 attLen + 1, (int *)buf);
147               if (rc == CDI_NOERR && attLen)
148                 {
149                   const int *restrict ip = (const int *)buf;
150                   printf("%d", ip[0]);
151                   for (size_t i = 1; i < (size_t)attLen; ++i)
152                     printf(", %d", ip[i]);
153                 }
154               break;
155             }
156 
157           if (rc == CDI_NOERR)
158             {
159               putchar('\n');
160             }
161           else
162             {
163               puts("error retrieving value");
164             }
165         }
166     }
167   free(buf);
168 }
169 
170 
171 /*
172  * Local Variables:
173  * c-file-style: "Java"
174  * c-basic-offset: 2
175  * indent-tabs-mode: nil
176  * show-trailing-whitespace: t
177  * require-trailing-newline: t
178  * End:
179  */
180