|
Packit |
a4aae4 |
// Ancillary.cc
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//#define DODS_DEBUG
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "Ancillary.h"
|
|
Packit |
a4aae4 |
#include "debug.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifndef WIN32
|
|
Packit |
a4aae4 |
#ifdef HAVE_UNISTD_H
|
|
Packit |
a4aae4 |
#include <unistd.h>
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
#include <io.h>
|
|
Packit |
a4aae4 |
#include <fcntl.h>
|
|
Packit |
a4aae4 |
#include <process.h>
|
|
Packit |
a4aae4 |
// Win32 does not define this. 08/21/02 jhrg
|
|
Packit |
a4aae4 |
#define F_OK 0
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** This function accepts a dataset path name, and searches for a
|
|
Packit |
a4aae4 |
matching ancillary data file name with a very specific set of
|
|
Packit |
a4aae4 |
search rules, given here:
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
directory filename extension
|
|
Packit |
a4aae4 |
same same `.'given
|
|
Packit |
a4aae4 |
given same `.'given
|
|
Packit |
a4aae4 |
same given `.'given
|
|
Packit |
a4aae4 |
given given `.'given
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Where ``same'' refers to the input dataset pathname, and ``given''
|
|
Packit |
a4aae4 |
refers to the function arguments.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
For example, If you call this function with a
|
|
Packit |
a4aae4 |
dataset name of <tt>/a/data</tt>, an extension of <tt>das</tt>, a
|
|
Packit |
a4aae4 |
directory of
|
|
Packit |
a4aae4 |
<tt>b</tt>, and a filename of <tt>ralph</tt>, the function will
|
|
Packit |
a4aae4 |
look (in order)
|
|
Packit |
a4aae4 |
for the following files:
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/a/data.das
|
|
Packit |
a4aae4 |
/b/data.das
|
|
Packit |
a4aae4 |
/a/ralph.das
|
|
Packit |
a4aae4 |
/b/ralph.das
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
The function will return a string containing the name of the first
|
|
Packit |
a4aae4 |
file in the list that exists, if any.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note This code now checks for pathname.ext 3/17/99 jhrg
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Find a file with ancillary data.
|
|
Packit |
a4aae4 |
@param pathname The input pathname of a dataset.
|
|
Packit |
a4aae4 |
@param ext The input extension the desired file is to have.
|
|
Packit |
a4aae4 |
@param dir The input directory in which the desired file may be
|
|
Packit |
a4aae4 |
found.
|
|
Packit |
a4aae4 |
@param file The input filename the desired file may have.
|
|
Packit |
a4aae4 |
@return A string containing the pathname of the file found by
|
|
Packit |
a4aae4 |
searching with the given components. If no file was found, the
|
|
Packit |
a4aae4 |
null string is returned.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
string
|
|
Packit |
a4aae4 |
Ancillary::find_ancillary_file( const string &pathname,
|
|
Packit |
a4aae4 |
const string &ext,
|
|
Packit |
a4aae4 |
const string &dir,
|
|
Packit |
a4aae4 |
const string &file )
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string::size_type slash = pathname.rfind('/') + 1;
|
|
Packit |
a4aae4 |
string directory = pathname.substr(0, slash);
|
|
Packit |
a4aae4 |
string filename = pathname.substr(slash);
|
|
Packit |
a4aae4 |
string basename = pathname.substr(slash, pathname.rfind('.') - slash);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "find ancillary file params: " << pathname << ", " << ext
|
|
Packit |
a4aae4 |
<< ", " << dir << ", " << file << endl);
|
|
Packit |
a4aae4 |
DBG(cerr << "find ancillary file comp: " << directory << ", " << filename
|
|
Packit |
a4aae4 |
<< ", " << basename << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string dot_ext = "." + ext;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string name = directory + basename + dot_ext;
|
|
Packit |
a4aae4 |
if (access(name.c_str(), F_OK) == 0)
|
|
Packit |
a4aae4 |
return name;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
name = pathname + dot_ext;
|
|
Packit |
a4aae4 |
if (access(name.c_str(), F_OK) == 0)
|
|
Packit |
a4aae4 |
return name;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
name = directory + ext;
|
|
Packit |
a4aae4 |
if (access(name.c_str(), F_OK) == 0)
|
|
Packit |
a4aae4 |
return name;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
name = dir + basename + dot_ext;
|
|
Packit |
a4aae4 |
if (access(name.c_str(), F_OK) == 0)
|
|
Packit |
a4aae4 |
return name;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
name = directory + file + dot_ext;
|
|
Packit |
a4aae4 |
if (access(name.c_str(), F_OK) == 0)
|
|
Packit |
a4aae4 |
return name;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
name = dir + file + dot_ext;
|
|
Packit |
a4aae4 |
if (access(name.c_str(), F_OK) == 0)
|
|
Packit |
a4aae4 |
return name;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
name = dir + ext;
|
|
Packit |
a4aae4 |
if (access(name.c_str(), F_OK) == 0)
|
|
Packit |
a4aae4 |
return name;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return "";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Given a pathname to a datafile, take that pathname apart and look for an
|
|
Packit |
a4aae4 |
// ancillary file that describes a group of datafiles of which this datafile
|
|
Packit |
a4aae4 |
// is a member. Assume that groups follow a simple naming convention where
|
|
Packit |
a4aae4 |
// files use either leading or trailing digits and a common basename to name
|
|
Packit |
a4aae4 |
// group members. For example, 00stuff.hdf, 01stuff.hdf, 02stuff.hdf, ..., is
|
|
Packit |
a4aae4 |
// a group and is has `stuff' as its basename.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Assume that <tt>name</tt> refers to a file that is one of a
|
|
Packit |
a4aae4 |
group of files which share a common `base' name and differ only by
|
|
Packit |
a4aae4 |
some prefix or suffix digits (e.g. <tt>00base</tt>, <tt>01base</tt>,
|
|
Packit |
a4aae4 |
... or <tt>base00</tt>, ... have the base name <tt>base</tt>). This
|
|
Packit |
a4aae4 |
function looks for a file <tt>base.ext</tt>.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param name The name (full or relative) to one member of a group
|
|
Packit |
a4aae4 |
of files.
|
|
Packit |
a4aae4 |
@param ext The extension of the group's ancillary file. Note that
|
|
Packit |
a4aae4 |
<tt>ext</tt> should include a period (.) if that needs to
|
|
Packit |
a4aae4 |
separate the base name from the extension.
|
|
Packit |
a4aae4 |
@return The pathname to the group's ancillary file if found, otherwise
|
|
Packit |
a4aae4 |
the empty string (""). */
|
|
Packit |
a4aae4 |
string
|
|
Packit |
a4aae4 |
Ancillary::find_group_ancillary_file( const string &name, const string &ext )
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// Given /usr/local/data/stuff.01.nc
|
|
Packit |
a4aae4 |
// pathname = /usr/local/data, filename = stuff.01.nc and
|
|
Packit |
a4aae4 |
// rootname = stuff.01
|
|
Packit |
a4aae4 |
string::size_type slash = name.find_last_of('/');
|
|
Packit |
a4aae4 |
string dirname = name.substr(0, slash);
|
|
Packit |
a4aae4 |
string filename = name.substr(slash + 1);
|
|
Packit |
a4aae4 |
string rootname = filename.substr(0, filename.find_last_of('.'));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Instead of using regexs, scan the filename for leading and then
|
|
Packit |
a4aae4 |
// trailing digits.
|
|
Packit |
a4aae4 |
string::iterator rootname_iter = rootname.begin();
|
|
Packit |
a4aae4 |
string::iterator rootname_end_iter = rootname.end();
|
|
Packit |
a4aae4 |
if (isdigit(*rootname_iter)) {
|
|
Packit |
a4aae4 |
while (rootname_iter != rootname_end_iter
|
|
Packit |
a4aae4 |
&& isdigit(*++rootname_iter))
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// We want: new_name = dirname + "/" + <base> + ext but without
|
|
Packit |
a4aae4 |
// creating a bunch of temp objects.
|
|
Packit |
a4aae4 |
string new_name = dirname;
|
|
Packit |
a4aae4 |
new_name.append("/");
|
|
Packit |
a4aae4 |
new_name.append(rootname_iter, rootname_end_iter);
|
|
Packit |
a4aae4 |
new_name.append(ext);
|
|
Packit |
a4aae4 |
DBG(cerr << "New Name (iter): " << new_name << endl);
|
|
Packit |
a4aae4 |
if (access(new_name.c_str(), F_OK) == 0) {
|
|
Packit |
a4aae4 |
return new_name;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string::reverse_iterator rootname_riter = rootname.rbegin();
|
|
Packit |
a4aae4 |
string::reverse_iterator rootname_end_riter = rootname.rend();
|
|
Packit |
a4aae4 |
if (isdigit(*rootname_riter)) {
|
|
Packit |
a4aae4 |
while (rootname_riter != rootname_end_riter
|
|
Packit |
a4aae4 |
&& isdigit(*++rootname_riter))
|
|
Packit |
a4aae4 |
;
|
|
Packit |
a4aae4 |
string new_name = dirname;
|
|
Packit |
a4aae4 |
new_name.append("/");
|
|
Packit |
a4aae4 |
// I used reverse iters to scan rootname backwards. To avoid
|
|
Packit |
a4aae4 |
// reversing the fragment between end_riter and riter, pass append
|
|
Packit |
a4aae4 |
// regular iters obtained using reverse_iterator::base(). See Meyers
|
|
Packit |
a4aae4 |
// p. 123. 1/22/2002 jhrg
|
|
Packit |
a4aae4 |
new_name.append(rootname_end_riter.base(), rootname_riter.base());
|
|
Packit |
a4aae4 |
new_name.append(ext);
|
|
Packit |
a4aae4 |
DBG(cerr << "New Name (riter): " << new_name << endl);
|
|
Packit |
a4aae4 |
if (access(new_name.c_str(), F_OK) == 0) {
|
|
Packit |
a4aae4 |
return new_name;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// If we're here either the file does not begin with leading digits or a
|
|
Packit |
a4aae4 |
// template made by removing those digits was not found.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return "";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Ancillary::read_ancillary_das( DAS &das,
|
|
Packit |
a4aae4 |
const string &pathname,
|
|
Packit |
a4aae4 |
const string &dir,
|
|
Packit |
a4aae4 |
const string &file )
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string name = find_ancillary_file( pathname, "das", dir, file ) ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "In Ancillary::read_ancillary_dds: name:" << name << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
FILE *in = fopen( name.c_str(), "r" ) ;
|
|
Packit |
a4aae4 |
if( in ) {
|
|
Packit |
a4aae4 |
das.parse( in ) ;
|
|
Packit |
a4aae4 |
(void)fclose( in ) ;
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
int res = fclose( in ) ;
|
|
Packit |
a4aae4 |
if( res )
|
|
Packit |
a4aae4 |
DBG(cerr << "Ancillary::read_ancillary_das - Failed to close file " << (void *)in << endl) ;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Ancillary::read_ancillary_dds( DDS &dds,
|
|
Packit |
a4aae4 |
const string &pathname,
|
|
Packit |
a4aae4 |
const string &dir,
|
|
Packit |
a4aae4 |
const string &file )
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string name = find_ancillary_file( pathname, "dds", dir, file ) ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "In Ancillary::read_ancillary_dds: name:" << name << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
FILE *in = fopen( name.c_str(), "r" ) ;
|
|
Packit |
a4aae4 |
if( in ) {
|
|
Packit |
a4aae4 |
dds.parse( in ) ;
|
|
Packit |
a4aae4 |
(void)fclose( in ) ;
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
int res = fclose( in ) ;
|
|
Packit |
a4aae4 |
if( res )
|
|
Packit |
a4aae4 |
DBG(cerr << "Ancillary::read_ancillary_das - Failed to close file " << (void *)in << endl) ;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} // namespace libdap
|
|
Packit |
a4aae4 |
|