35 #include "config_ff.h"
37 static char rcsid[] not_used =
64 #include <InternalErr.h>
65 #include <dods-limits.h>
69 #include "FFRequestHandler.h"
87 static string &remove_paths(
string &src)
89 size_t p1 = src.find_first_of(
'/');
90 if (p1 == string::npos)
92 size_t p2 = src.find_last_of(
'/');
97 src.erase(p1, p2-p1+1);
120 static string freeform_error_message()
124 throw BESInternalError(
"Called the FreeForm error message code, but there was no error.", __FILE__, __LINE__);
128 if (is_a_warning(error))
134 string problem = error->problem;
135 string message = error->message;
136 oss << remove_paths(problem) <<
": " << remove_paths(message) << endl;
138 ff_destroy_error (error);
139 error = pull_error();
157 long read_ff(
const char *dataset,
const char *if_file,
const char *o_format,
char *o_buffer,
unsigned long bsize)
163 std_args = ff_create_std_args();
165 throw BESInternalError(
"FreeForm could not allocate a 'stdargs' object.", __FILE__, __LINE__);
169 std_args->error_prompt = FALSE;
170 std_args->user.is_stdin_redirected = 0;
171 std_args->input_file = (
char*) (dataset);
172 std_args->input_format_file = (
char*) (if_file);
173 std_args->output_file = NULL;
174 std_args->output_format_buffer = (
char*) (o_format);
175 std_args->log_file = (
char *)
"/dev/null";
178 std_args->log_file = (
char *)
"/tmp/ffdods.log";
187 bufsz->buffer = o_buffer;
188 bufsz->total_bytes = (FF_BSS_t) bsize;
189 bufsz->bytes_used = (FF_BSS_t) 0;
191 std_args->output_bufsize = bufsz;
193 newform_log = ff_create_bufsize(SCRATCH_QUANTA);
195 throw BESInternalError(
"FreeForm could not allocate a 'newform_log' object.", __FILE__, __LINE__);
200 int status = newform(std_args, newform_log, 0 );
202 BESDEBUG(
"ff",
"FreeForm: newform returns " << status << endl);
205 string message = freeform_error_message();
206 BESDEBUG(
"ff",
"FreeForm: error message " << message << endl);
207 throw BESError(message, BES_SYNTAX_USER_ERROR, __FILE__, __LINE__);
210 ff_destroy_bufsize(newform_log);
211 ff_destroy_std_args(std_args);
213 return bufsz->bytes_used;
217 ff_destroy_bufsize(newform_log);
219 ff_destroy_std_args(std_args);
233 void free_ff_char_vector(
char **v,
int len)
235 for (
int i = 0; i < len; ++i)
248 const string ff_types(
Type dods_type)
270 throw Error(
"ff_types: DODS type " + D2type_name(dods_type) +
" does not map to a FreeForm type.");
280 int ff_prec(
Type dods_type)
297 throw Error(
"ff_prec: DODS type " + D2type_name(dods_type) +
" does not map to a FreeForm type.");
307 make_output_format(
const string & name,
Type type,
const int width)
311 str <<
"binary_output_data \"DODS binary output data\"" << endl;
312 str << name <<
" 1 " << width <<
" " << ff_types(type)
313 <<
" " << ff_prec(type) << endl;
320 makeND_output_format(
const string & name,
Type type,
const int width,
321 int ndim,
const long *start,
const long *edge,
const
322 long *stride,
string * dname)
325 str <<
"binary_output_data \"DODS binary output data\"" << endl;
326 str << name <<
" 1 " << width <<
" ARRAY";
328 for (
int i = 0; i < ndim; i++)
329 str <<
"[" <<
"\"" << dname[i] <<
"\" " << start[i] + 1 <<
" to "
330 << start[i] + (edge[i] - 1) * stride[i] +
331 1 <<
" by " << stride[i] <<
" ]";
333 str <<
" of " << ff_types(type) <<
" " << ff_prec(type) << endl;
335 DBG(cerr <<
"ND output format: " << str.str() << endl);
345 const string & format_delimiter(
const string & new_delimiter)
347 static string delimiter =
".";
349 if (new_delimiter !=
"")
350 delimiter = new_delimiter;
361 const string & format_extension(
const string & new_extension)
363 static string extension =
".fmt";
365 if (new_extension !=
"")
366 extension = new_extension;
377 if (src_conduit->input && trg_conduit->input)
378 return (
bool) ff_format_comp(src_conduit->input->fd->format,
379 trg_conduit->input->fd->format);
380 else if (src_conduit->output && trg_conduit->output)
381 return (
bool) ff_format_comp(src_conduit->output->fd->format,
382 trg_conduit->output->fd->format);
390 error = list_replace_items((pgenobj_cmp_t) cmp_array_conduit,
411 snprintf(Msgt, Msgt_size,
"Error: NULL DATA_BIN_HANDLE in %s", ROUTINE_NAME);
416 *dbin_h = db_make(std_args->input_file);
419 snprintf(Msgt, Msgt_size,
"Error in Standard Data Bin");
420 return (ERR_MEM_LACK);
426 if (db_set(*dbin_h, DBSET_READ_EQV, std_args->input_file)) {
427 snprintf(Msgt, Msgt_size,
"Error making name table for %s",
428 std_args->input_file);
429 return (DBSET_READ_EQV);
434 std_args->input_file,
435 std_args->output_file,
436 std_args->input_format_file,
437 std_args->input_format_buffer,
438 std_args->input_format_title, &format_data_list)) {
439 if (format_data_list)
440 dll_free_holdings(format_data_list);
442 snprintf(Msgt, Msgt_size,
"Error setting an input format for %s",
443 std_args->input_file);
444 return (DBSET_INPUT_FORMATS);
448 db_set(*dbin_h, DBSET_CREATE_CONDUITS, std_args, format_data_list);
449 dll_free_holdings(format_data_list);
451 snprintf(Msgt, Msgt_size,
"Error creating array information for %s",
452 std_args->input_file);
453 return (DBSET_CREATE_CONDUITS);
456 if (db_set(*dbin_h, DBSET_HEADER_FILE_NAMES, FFF_INPUT,
457 std_args->input_file)) {
458 snprintf(Msgt, Msgt_size,
"Error determining input header file names for %s",
459 std_args->input_file);
460 return (DBSET_HEADER_FILE_NAMES);
463 if (db_set(*dbin_h, DBSET_HEADERS)) {
464 snprintf(Msgt, Msgt_size,
"getting header file for %s", std_args->input_file);
465 return (DBSET_HEADERS);
469 if (db_set(*dbin_h, DBSET_INIT_CONDUITS, FFF_DATA,
470 std_args->records_to_read)) {
471 snprintf(Msgt, Msgt_size,
"Error creating array information for %s",
472 std_args->input_file);
473 return (DBSET_INIT_CONDUITS);
476 error = merge_redundant_conduits((*dbin_h)->array_conduit_list);
478 snprintf(Msgt, Msgt_size,
"Error merging redundent conduits");
488 long Records(
const string &filename)
495 static char Msgt[255];
497 SetUps = ff_create_std_args();
503 SetUps->user.is_stdin_redirected = 0;
504 SetUps->input_file =
const_cast<char*
>(filename.c_str());
506 SetUps->output_file = NULL;
508 error = SetDodsDB(SetUps, &dbin, Msgt);
509 if (error && error < ERR_WARNING_ONLY) {
510 ff_destroy_std_args(SetUps);
515 ff_destroy_std_args(SetUps);
517 error = db_ask(dbin, DBASK_PROCESS_INFO, FFF_INPUT | FFF_DATA, &pinfo_list);
521 pinfo_list = dll_first(pinfo_list);
525 long num_records = PINFO_SUPER_ARRAY_ELS(pinfo);
527 ff_destroy_process_info_list(pinfo_list);
534 bool file_exist(
const char *filename)
536 return access(filename, F_OK) == 0;
552 find_ancillary_rss_formats(
const string & dataset,
const string & ,
556 string FormatPath = FFRequestHandler::get_RSS_format_files();
562 size_t delim = dataset.rfind(
"#");
563 if (delim != string::npos)
564 FileName = dataset.substr(delim + 1, dataset.length() - delim + 1);
566 delim = dataset.rfind(
"/");
567 if (delim != string::npos)
568 FileName = dataset.substr(delim + 1, dataset.length() - delim + 1);
574 delim = FileName.find(
"_");
575 if ( delim != string::npos ) {
576 BaseName = FileName.substr(0,delim+1);
579 throw Error(
"Could not find input format for: " + dataset);
583 string DatePart = FileName.substr(delim+1, FileName.length()-delim+1);
585 if (FormatPath[FormatPath.length()-1] !=
'/')
586 FormatPath.append(
"/");
588 if ( (DatePart.find(
"_") != string::npos) || (DatePart.length() < 10) )
589 FormatFile = FormatPath + BaseName +
"averaged.fmt";
591 FormatFile = FormatPath + BaseName +
"daily.fmt";
593 return string(FormatFile);
609 find_ancillary_rss_das(
const string & dataset,
const string & ,
613 string FormatPath = FFRequestHandler::get_RSS_format_files();
617 size_t delim = dataset.rfind(
"#");
618 if (delim != string::npos)
619 FileName = dataset.substr(delim + 1, dataset.length() - delim + 1);
621 delim = dataset.rfind(
"/");
622 if (delim != string::npos)
623 FileName = dataset.substr(delim + 1, dataset.length() - delim + 1);
628 delim = FileName.find(
"_");
629 if ( delim != string::npos ) {
630 BaseName = FileName.substr(0,delim+1);
633 string msg =
"Could not find input format for: ";
635 throw InternalErr(msg);
638 string DatePart = FileName.substr(delim+1, FileName.length()-delim+1);
640 if (FormatPath[FormatPath.length()-1] !=
'/')
641 FormatPath.append(
"/");
643 if ( (DatePart.find(
"_") != string::npos) || (DatePart.length() < 10) )
644 FormatFile = FormatPath + BaseName +
"averaged.das";
646 FormatFile = FormatPath + BaseName +
"daily.das";
648 return string(FormatFile);
654 bool is_integer_type(BaseType * btp)
656 switch (btp->type()) {
672 case dods_structure_c:
673 case dods_sequence_c:
680 bool is_float_type(BaseType * btp)
682 switch (btp->type()) {
698 case dods_structure_c:
699 case dods_sequence_c:
710 dods_uint32 get_integer_value(BaseType * var)
throw(InternalErr)
715 switch (var->type()) {
717 return static_cast<Byte*
>(var)->value();
720 return static_cast<Int16*
>(var)->value();
723 return static_cast<Int32*
>(var)->value();
726 return static_cast<UInt16*
>(var)->value();
729 return static_cast<UInt32*
>(var)->value();
732 throw InternalErr(__FILE__, __LINE__,
733 "Tried to get an integer value for a non-integer datatype!");
737 dods_float64 get_float_value(BaseType * var)
throw(InternalErr)
742 switch (var->type()) {
747 return get_integer_value(var);
750 return static_cast<Float32*
>(var)->value();
753 return static_cast<Float64*
>(var)->value();
756 throw InternalErr(__FILE__, __LINE__,
757 "Tried to get an float value for a non-numeric datatype!");
761 string get_Regex_format_file(
const string & filename)
763 string::size_type found = filename.find_last_of(
"/\\");
764 string base_name = filename.substr(found+1);
766 std::map<string,string> mapFF = FFRequestHandler::get_fmt_regex_map();
767 for (
auto rgx = mapFF.begin(); rgx != mapFF.end(); ++ rgx) {
768 BESDEBUG(
"ff",
"get_Regex_format_file() - filename: '" << filename <<
"'" <<
769 " regex: '" << (*rgx).first <<
"'" <<
770 " format: '" << (*rgx).second <<
"'" << endl);
771 BESRegex regex(((*rgx).first).c_str());
772 if ( (
unsigned long) regex.match(base_name.c_str(), base_name.length()) == base_name.length() ){
773 retVal = string((*rgx).second);
777 BESDEBUG(
"ff",
"get_Regex_format_file() - returning format filename: '"<< retVal <<
"'" << endl);