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