bes  Updated for version 3.20.6
ffdds.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of ff_handler a FreeForm API handler for the OPeNDAP
4 // DAP2 data server.
5 
6 // Copyright (c) 2005 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This is free software; you can redistribute it and/or modify it under the
10 // terms of the GNU Lesser General Public License as published by the Free
11 // Software Foundation; either version 2.1 of the License, or (at your
12 // option) any later version.
13 //
14 // This software is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 // License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 // (c) COPYRIGHT URI/MIT 1997-99
25 // Please read the full copyright statement in the file COPYRIGHT.
26 //
27 // Authors: reza (Reza Nekovei)
28 
29 // This file contains functions which read the variables and their description
30 // from a freeform API and build the in-memory DDS. These functions form the
31 // core of the server-side software necessary to extract the DDS from a
32 // FreeForm data file.
33 //
34 // It also contains test code which will print the in-memory DDS to
35 // stdout.
36 //
37 // ReZa 6/20/97
38 
39 #include "config_ff.h"
40 
41 #include <cstdio>
42 #include <cstring>
43 
44 #include <iostream>
45 #include <string>
46 
47 #include <Error.h>
48 #include <InternalErr.h>
49 #include <mime_util.h>
50 #include <util.h>
51 
52 #include "FreeFormCPP.h"
53 
54 #include <DDS.h>
55 
56 #include "FFInt16.h"
57 #include "FFUInt16.h"
58 #include "FFInt32.h"
59 #include "FFUInt32.h"
60 #include "FFFloat32.h"
61 #include "FFFloat64.h"
62 #include "FFByte.h"
63 #include "FFArray.h"
64 #include "FFSequence.h"
65 #include "FFGrid.h"
66 #include "FFStr.h"
67 #include "util_ff.h"
68 
69 #include "FFRequestHandler.h"
70 
71 void ff_read_descriptors(DDS &dds_table, const string &filename)
72 {
73  if (!file_exist(filename.c_str()))
74  throw Error((string) "Could not open file " + path_to_filename(filename) + string("."));
75 
76  // Set dataset name
77  dds_table.set_dataset_name(name_path(filename));
78 
79  FF_STD_ARGS_PTR SetUps = NULL;
80  SetUps = ff_create_std_args();
81  if (!SetUps)
82  throw Error("Insufficient memory");
83 
84  // Set the structure values to create the FreeForm DB
85  SetUps->user.is_stdin_redirected = 0;
86 
87  SetUps->input_file = const_cast<char*>(filename.c_str());
88 
89  // Setting the input format file here causes db_set (called by SetDodsDB)
90  // to not set that field of SetUps. In the original modification for the
91  // RSS-hosted data, the server also called this code in FFArray.cc and
92  // FFSequence. However, in a later version of the handler I moved the
93  // format finding code here and recorded the results in the various
94  // objects (including FFArray, ...). So I think the RSS format-specific
95  // code in those classes is not needed anymore. I'm going to #if 0 #endif
96  // them out and check in the result. 10/30/08 jhrg
97  string iff = "";
98  if (FFRequestHandler::get_RSS_format_support()) {
99  iff = find_ancillary_rss_formats(filename);
100  SetUps->input_format_file = const_cast<char*>(iff.c_str());
101  }
102  // Regex support
103  if (FFRequestHandler::get_Regex_format_support()) {
104  iff = get_Regex_format_file(filename);
105  if (!iff.empty())
106  SetUps->input_format_file = const_cast<char*>(iff.c_str());
107  }
108 
109  SetUps->output_file = NULL;
110 
111  DATA_BIN_PTR dbin = NULL;
112  char Msgt[Msgt_size];
113  int error = SetDodsDB(SetUps, &dbin, Msgt);
114  if (error && error < ERR_WARNING_ONLY) {
115  if (dbin)
116  db_destroy(dbin);
117  ff_destroy_std_args(SetUps);
118  string msg = (string) Msgt + " FreeForm error code: ";
119  append_long_to_string((long) error, 10, msg);
120  throw Error(msg);
121  }
122 
123  ff_destroy_std_args(SetUps);
124 
125  // These things are defined here so that they can be freed in the catch(...)
126  // clause below
127  PROCESS_INFO_LIST pinfo_list = NULL;
128  char **var_names_vector = NULL;
129  char **dim_names_vector = NULL;
130  Array *ar = NULL;
131  Sequence *seq = NULL;
132 
133  try {
134 
135  int num_names = 0;
136  error = db_ask(dbin, DBASK_VAR_NAMES, FFF_INPUT | FFF_DATA, &num_names, &var_names_vector);
137  if (error) {
138  string msg = "Could not get variable list from the input file. FreeForm error code: ";
139  append_long_to_string((long) error, 10, msg);
140  throw Error(msg);
141  }
142 
143  error = db_ask(dbin, DBASK_PROCESS_INFO, FFF_INPUT | FFF_DATA, &pinfo_list);
144  if (error) {
145  string msg = "Could not get process info for the input file. FreeForm error code: ";
146  append_long_to_string((long) error, 10, msg);
147  throw Error(msg);
148  }
149 
150  bool newseq = true;
151  bool is_array = true;
152  for (int i = 0; i < num_names; i++) {
153  int num_dim_names = 0;
154 
155  char *cp = NULL;
156 
157  error = db_ask(dbin, DBASK_ARRAY_DIM_NAMES, var_names_vector[i], &num_dim_names, &dim_names_vector);
158  if (error) {
159  string msg = "Could not get array dimension names for variable: ";
160  msg += (string) var_names_vector[i] + ", FreeForm error code: ";
161  append_long_to_string((long) error, 10, msg);
162  throw Error(msg);
163  }
164 
165  if (num_dim_names == 0) // sequence names
166  cp = var_names_vector[i];
167  else {
168  cp = strstr(var_names_vector[i], "::");
169  // If cp is not null, advance past the "::"
170  if (cp)
171  cp += 2;
172  }
173 
174  pinfo_list = dll_first(pinfo_list);
175  PROCESS_INFO_PTR pinfo = ((PROCESS_INFO_PTR) (pinfo_list)->data.u.pi);
176  FORMAT_PTR iformat = PINFO_FORMAT(pinfo);
177  VARIABLE_PTR var = ff_find_variable(cp, iformat);
178 
179  // For some formats Freefrom sends an extra EOL variable at the end of
180  // the list.
181  if (IS_EOL(var)) {
182  memFree(dim_names_vector, "**dim_names_vector");
183  dim_names_vector = NULL;
184  break;
185  }
186 
187  while (!var) { // search formats in the format list for the variable
188  pinfo_list = (pinfo_list)->next;
189  pinfo = ((PROCESS_INFO_PTR) (pinfo_list)->data.u.pi);
190 
191  if (!pinfo) {
192  string msg = "Variable " + (string)cp + " was not found in the format file.";
193  throw Error(msg);
194  }
195 
196  iformat = PINFO_FORMAT(pinfo);
197  var = ff_find_variable(cp, iformat);
198  }
199 
200  string input_format_file = PINFO_ORIGIN(pinfo);
201 
202  BaseType *bt = NULL;
203  switch (FFV_DATA_TYPE(var)) {
204  case FFV_TEXT:
205  bt = new FFStr(cp, filename);
206  static_cast<FFStr&>(*bt).set_length(var->end_pos - var->start_pos + 1);
207  break;
208 
209  case FFV_INT8:
210  bt = new FFByte(cp, filename);
211  break;
212 
213  case FFV_UINT8:
214  bt = new FFByte(cp, filename); // Byte is unsigned.
215  break;
216 
217  case FFV_INT16:
218  bt = new FFInt16(cp, filename);
219  break;
220 
221  case FFV_UINT16:
222  bt = new FFUInt16(cp, filename);
223  break;
224 
225  case FFV_INT32:
226  bt = new FFInt32(cp, filename);
227  break;
228 
229  case FFV_UINT32:
230  bt = new FFUInt32(cp, filename);
231  break;
232 
233  case FFV_INT64:
234  bt = new FFInt32(cp, filename); // Ouch!
235  break;
236 
237  case FFV_UINT64:
238  bt = new FFUInt32(cp, filename);
239  break;
240 
241  case FFV_FLOAT32:
242  bt = new FFFloat32(cp, filename);
243  break;
244 
245  case FFV_FLOAT64:
246  bt = new FFFloat64(cp, filename);
247  break;
248 
249  case FFV_ENOTE:
250  bt = new FFFloat64(cp, filename);
251  break;
252 
253  default:
254  throw InternalErr(__FILE__, __LINE__, "Unknown FreeForm type!");
255  }
256 
257  if (num_dim_names == 0) {
258  if (!seq || newseq) {
259  newseq = false;
260  // The format name cannot contain spaces! 8/12/98 jhrg
261  seq = new FFSequence(iformat->name, filename, input_format_file);
262  }
263  seq->add_var_nocopy(bt);
264  is_array = false;
265  }
266  else {
267  ar = new FFArray(cp, filename, bt, input_format_file);
268  delete bt;
269  newseq = true; // An array terminates the old sequence
270  is_array = true;
271  //} The follow loop was separate from this else clause but the
272  // loop won't run if num_dim_names is not > 0
273 
274  for (int j = 0; j < num_dim_names; j++) {
275  FF_ARRAY_DIM_INFO_PTR array_dim_info = NULL;
276 
277  error = db_ask(dbin, DBASK_ARRAY_DIM_INFO, var_names_vector[i], dim_names_vector[j],
278  &array_dim_info);
279  if (error) {
280  string msg = string("Could not get array dimension info for variable ")
281  + string(var_names_vector[i]) + string(", FreeForm error code: ");
282  append_long_to_string((long) error, 10, msg);
283  throw Error(msg);
284  }
285 
286  int DimSiz = (array_dim_info->end_index - array_dim_info->start_index + 1)
287  / array_dim_info->granularity;
288  ar->append_dim(DimSiz, (string) dim_names_vector[j]);
289 
290  memFree(array_dim_info, "");
291  array_dim_info = NULL;
292  }
293  }
294 
295  memFree(dim_names_vector, "**dim_names_vector");
296  dim_names_vector = NULL;
297 
298  if (is_array)
299  dds_table.add_var_nocopy(ar);
300  else if (newseq)
301  dds_table.add_var_nocopy(seq);
302  } // End of the for num_names.
303 
304  if (!is_array)
305  dds_table.add_var_nocopy(seq);
306  }
307  catch (...) {
308  // Because these are added to the DDS using the nocopy methods,
309  // they should only be deleted when an excpetion is thrown
310  delete seq;
311  delete ar;
312 
313  if (dbin)
314  db_destroy(dbin);
315  if (var_names_vector)
316  memFree(var_names_vector, "**var_names_vector");
317  if (pinfo_list)
318  ff_destroy_process_info_list(pinfo_list);
319  if (dim_names_vector)
320  memFree(dim_names_vector, "**dim_names_vector");
321 
322  throw;
323  }
324 
325  if (dbin)
326  db_destroy(dbin);
327  if (var_names_vector)
328  memFree(var_names_vector, "**var_names_vector");
329  if (pinfo_list)
330  ff_destroy_process_info_list(pinfo_list);
331  if (dim_names_vector)
332  memFree(dim_names_vector, "**dim_names_vector");
333 }
struct_ff_std_args
Definition: freeform.h:867
struct_ff_dll_node
Definition: freeform.h:1278
struct_ff_process_info
Definition: freeform.h:1193
FFSequence
Definition: FFSequence.h:45
FFByte
Definition: FFByte.h:51
FFFloat32
Definition: FFFloat32.h:39
struct_ff_variable
Definition: freeform.h:1034
FFArray
Definition: FFArray.h:45
FFFloat64
Definition: FFFloat64.h:45
FFUInt32
Definition: FFUInt32.h:45
FFUInt16
Definition: FFUInt16.h:39
struct_databin
Definition: freeform.h:1294
FFInt16
Definition: FFInt16.h:39
Error
FFInt32
Definition: FFInt32.h:45
struct_ff_array_dim_info
Definition: freeform.h:1308
struct_ff_format
Definition: freeform.h:973
FFStr
Definition: FFStr.h:47