libdap++ Updated for version 3.8.2

Ancillary.cc

Go to the documentation of this file.
00001 // Ancillary.cc
00002 
00003 #include "config.h"
00004 #include "Ancillary.h"
00005 #include "debug.h"
00006 
00007 #ifndef WIN32
00008 #ifdef HAVE_UNISTD_H
00009 #include <unistd.h>
00010 #endif
00011 #else
00012 #include <io.h>
00013 #include <fcntl.h>
00014 #include <process.h>
00015 // Win32 does not define this. 08/21/02 jhrg
00016 #define F_OK 0
00017 #endif
00018 
00019 namespace libdap {
00020 
00065 string
00066 Ancillary::find_ancillary_file( const string &pathname,
00067                                 const string &ext,
00068                                 const string &dir,
00069                                 const string &file )
00070 {
00071     string::size_type slash = pathname.rfind('/') + 1;
00072     string directory = pathname.substr(0, slash);
00073     string filename = pathname.substr(slash);
00074     string basename = pathname.substr(slash, pathname.rfind('.') - slash);
00075 
00076     DBG(cerr << "find ancillary file params: " << pathname << ", " << ext
00077         << ", " << dir << ", " << file << endl);
00078     DBG(cerr << "find ancillary file comp: " << directory << ", " << filename
00079         << ", " << basename << endl);
00080 
00081     string dot_ext = "." + ext;
00082 
00083     string name = directory + basename + dot_ext;
00084     if (access(name.c_str(), F_OK) == 0)
00085         return name;
00086 
00087     name = pathname + dot_ext;
00088     if (access(name.c_str(), F_OK) == 0)
00089         return name;
00090 
00091     name = directory + ext;
00092     if (access(name.c_str(), F_OK) == 0)
00093         return name;
00094 
00095     name = dir + basename + dot_ext;
00096     if (access(name.c_str(), F_OK) == 0)
00097         return name;
00098 
00099     name = directory + file + dot_ext;
00100     if (access(name.c_str(), F_OK) == 0)
00101         return name;
00102 
00103     name = dir + file + dot_ext;
00104     if (access(name.c_str(), F_OK) == 0)
00105         return name;
00106 
00107     name = dir + ext;
00108     if (access(name.c_str(), F_OK) == 0)
00109         return name;
00110 
00111     return "";
00112 }
00113 
00114 // Given a pathname to a datafile, take that pathname apart and look for an
00115 // ancillary file that describes a group of datafiles of which this datafile
00116 // is a member. Assume that groups follow a simple naming convention where
00117 // files use either leading or trailing digits and a common basename to name
00118 // group members. For example, 00stuff.hdf, 01stuff.hdf, 02stuff.hdf, ..., is
00119 // a group and is has `stuff' as its basename.
00120 
00134 string
00135 Ancillary::find_group_ancillary_file( const string &name, const string &ext )
00136 {
00137     // Given /usr/local/data/stuff.01.nc
00138     // pathname = /usr/local/data, filename = stuff.01.nc and
00139     // rootname = stuff.01
00140     string::size_type slash = name.find_last_of('/');
00141     string dirname = name.substr(0, slash);
00142     string filename = name.substr(slash + 1);
00143     string rootname = filename.substr(0, filename.find_last_of('.'));
00144 
00145     // Instead of using regexs, scan the filename for leading and then
00146     // trailing digits.
00147     string::iterator rootname_iter = rootname.begin();
00148     string::iterator rootname_end_iter = rootname.end();
00149     if (isdigit(*rootname_iter)) {
00150         while (rootname_iter != rootname_end_iter
00151                && isdigit(*++rootname_iter))
00152             ;
00153 
00154         // We want: new_name = dirname + "/" + <base> + ext but without
00155         // creating a bunch of temp objects.
00156         string new_name = dirname;
00157         new_name.append("/");
00158         new_name.append(rootname_iter, rootname_end_iter);
00159         new_name.append(ext);
00160         DBG(cerr << "New Name (iter): " << new_name << endl);
00161         if (access(new_name.c_str(), F_OK) == 0) {
00162             return new_name;
00163         }
00164     }
00165 
00166     string::reverse_iterator rootname_riter = rootname.rbegin();
00167     string::reverse_iterator rootname_end_riter = rootname.rend();
00168     if (isdigit(*rootname_riter)) {
00169         while (rootname_riter != rootname_end_riter
00170                && isdigit(*++rootname_riter))
00171             ;
00172         string new_name = dirname;
00173         new_name.append("/");
00174         // I used reverse iters to scan rootname backwards. To avoid
00175         // reversing the fragment between end_riter and riter, pass append
00176         // regular iters obtained using reverse_iterator::base(). See Meyers
00177         // p. 123. 1/22/2002 jhrg
00178         new_name.append(rootname_end_riter.base(), rootname_riter.base());
00179         new_name.append(ext);
00180         DBG(cerr << "New Name (riter): " << new_name << endl);
00181         if (access(new_name.c_str(), F_OK) == 0) {
00182             return new_name;
00183         }
00184     }
00185 
00186     // If we're here either the file does not begin with leading digits or a
00187     // template made by removing those digits was not found.
00188 
00189     return "";
00190 }
00191 
00192 void
00193 Ancillary::read_ancillary_das( DAS &das,
00194                                const string &pathname,
00195                                const string &dir,
00196                                const string &file )
00197 {
00198     string name = find_ancillary_file( pathname, "das", dir, file ) ;
00199 
00200     FILE *in = fopen( name.c_str(), "r" ) ;
00201     if( in ) {
00202         das.parse( in ) ;
00203         int res = fclose( in ) ;
00204         if( res )
00205             DBG(cerr << "DODSFilter::read_ancillary_das - Failed to close file " << (void *)in << endl) ;
00206     }
00207 }
00208 
00209 void
00210 Ancillary::read_ancillary_dds( DDS &dds,
00211                                const string &pathname,
00212                                const string &dir,
00213                                const string &file )
00214 {
00215     string name = find_ancillary_file( pathname, "dds", dir, file ) ;
00216 
00217     FILE *in = fopen( name.c_str(), "r" ) ;
00218     if( in ) {
00219         dds.parse( in ) ;
00220         int res = fclose( in ) ;
00221         if( res )
00222             DBG(cerr << "DODSFilter::read_ancillary_das - Failed to close file " << (void *)in << endl) ;
00223     }
00224 }
00225 
00226 } // namespace libdap
00227