1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
|
// Ancillary.cc
#include "config.h"
//#define DODS_DEBUG
#include "Ancillary.h"
#include "debug.h"
#ifndef WIN32
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#else
#include <io.h>
#include <fcntl.h>
#include <process.h>
// Win32 does not define this. 08/21/02 jhrg
#define F_OK 0
#endif
namespace libdap {
/** This function accepts a dataset path name, and searches for a
matching ancillary data file name with a very specific set of
search rules, given here:
<pre>
directory filename extension
same same `.'given
given same `.'given
same given `.'given
given given `.'given
</pre>
Where ``same'' refers to the input dataset pathname, and ``given''
refers to the function arguments.
For example, If you call this function with a
dataset name of <tt>/a/data</tt>, an extension of <tt>das</tt>, a
directory of
<tt>b</tt>, and a filename of <tt>ralph</tt>, the function will
look (in order)
for the following files:
<pre>
/a/data.das
/b/data.das
/a/ralph.das
/b/ralph.das
</pre>
The function will return a string containing the name of the first
file in the list that exists, if any.
@note This code now checks for <code>pathname.ext</code> 3/17/99 jhrg
@brief Find a file with ancillary data.
@param pathname The input pathname of a dataset.
@param ext The input extension the desired file is to have.
@param dir The input directory in which the desired file may be
found.
@param file The input filename the desired file may have.
@return A string containing the pathname of the file found by
searching with the given components. If no file was found, the
null string is returned.
*/
string
Ancillary::find_ancillary_file( const string &pathname,
const string &ext,
const string &dir,
const string &file )
{
string::size_type slash = pathname.rfind('/') + 1;
string directory = pathname.substr(0, slash);
string filename = pathname.substr(slash);
string basename = pathname.substr(slash, pathname.rfind('.') - slash);
DBG(cerr << "find ancillary file params: " << pathname << ", " << ext
<< ", " << dir << ", " << file << endl);
DBG(cerr << "find ancillary file comp: " << directory << ", " << filename
<< ", " << basename << endl);
string dot_ext = "." + ext;
string name = directory + basename + dot_ext;
if (access(name.c_str(), F_OK) == 0)
return name;
name = pathname + dot_ext;
if (access(name.c_str(), F_OK) == 0)
return name;
name = directory + ext;
if (access(name.c_str(), F_OK) == 0)
return name;
name = dir + basename + dot_ext;
if (access(name.c_str(), F_OK) == 0)
return name;
name = directory + file + dot_ext;
if (access(name.c_str(), F_OK) == 0)
return name;
name = dir + file + dot_ext;
if (access(name.c_str(), F_OK) == 0)
return name;
name = dir + ext;
if (access(name.c_str(), F_OK) == 0)
return name;
return "";
}
// Given a pathname to a datafile, take that pathname apart and look for an
// ancillary file that describes a group of datafiles of which this datafile
// is a member. Assume that groups follow a simple naming convention where
// files use either leading or trailing digits and a common basename to name
// group members. For example, 00stuff.hdf, 01stuff.hdf, 02stuff.hdf, ..., is
// a group and is has `stuff' as its basename.
/** Assume that <tt>name</tt> refers to a file that is one of a
group of files which share a common `base' name and differ only by
some prefix or suffix digits (e.g. <tt>00base</tt>, <tt>01base</tt>,
... or <tt>base00</tt>, ... have the base name <tt>base</tt>). This
function looks for a file <tt>base.ext</tt>.
@param name The name (full or relative) to one member of a group
of files.
@param ext The extension of the group's ancillary file. Note that
<tt>ext</tt> should include a period (.) if that needs to
separate the base name from the extension.
@return The pathname to the group's ancillary file if found, otherwise
the empty string (""). */
string
Ancillary::find_group_ancillary_file( const string &name, const string &ext )
{
// Given /usr/local/data/stuff.01.nc
// pathname = /usr/local/data, filename = stuff.01.nc and
// rootname = stuff.01
string::size_type slash = name.find_last_of('/');
string dirname = name.substr(0, slash);
string filename = name.substr(slash + 1);
string rootname = filename.substr(0, filename.find_last_of('.'));
// Instead of using regexs, scan the filename for leading and then
// trailing digits.
string::iterator rootname_iter = rootname.begin();
string::iterator rootname_end_iter = rootname.end();
if (isdigit(*rootname_iter)) {
while (rootname_iter != rootname_end_iter
&& isdigit(*++rootname_iter))
;
// We want: new_name = dirname + "/" + <base> + ext but without
// creating a bunch of temp objects.
string new_name = dirname;
new_name.append("/");
new_name.append(rootname_iter, rootname_end_iter);
new_name.append(ext);
DBG(cerr << "New Name (iter): " << new_name << endl);
if (access(new_name.c_str(), F_OK) == 0) {
return new_name;
}
}
string::reverse_iterator rootname_riter = rootname.rbegin();
string::reverse_iterator rootname_end_riter = rootname.rend();
if (isdigit(*rootname_riter)) {
while (rootname_riter != rootname_end_riter
&& isdigit(*++rootname_riter))
;
string new_name = dirname;
new_name.append("/");
// I used reverse iters to scan rootname backwards. To avoid
// reversing the fragment between end_riter and riter, pass append
// regular iters obtained using reverse_iterator::base(). See Meyers
// p. 123. 1/22/2002 jhrg
new_name.append(rootname_end_riter.base(), rootname_riter.base());
new_name.append(ext);
DBG(cerr << "New Name (riter): " << new_name << endl);
if (access(new_name.c_str(), F_OK) == 0) {
return new_name;
}
}
// If we're here either the file does not begin with leading digits or a
// template made by removing those digits was not found.
return "";
}
void
Ancillary::read_ancillary_das( DAS &das,
const string &pathname,
const string &dir,
const string &file )
{
string name = find_ancillary_file( pathname, "das", dir, file ) ;
DBG(cerr << "In Ancillary::read_ancillary_dds: name:" << name << endl);
FILE *in = fopen( name.c_str(), "r" ) ;
if( in ) {
das.parse( in ) ;
(void)fclose( in ) ;
}
}
void
Ancillary::read_ancillary_dds( DDS &dds,
const string &pathname,
const string &dir,
const string &file )
{
string name = find_ancillary_file( pathname, "dds", dir, file ) ;
DBG(cerr << "In Ancillary::read_ancillary_dds: name:" << name << endl);
FILE *in = fopen( name.c_str(), "r" ) ;
if( in ) {
dds.parse( in ) ;
(void)fclose( in ) ;
}
}
} // namespace libdap
|