libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
Ancillary.cc
Go to the documentation of this file.
1// Ancillary.cc
2
3#include "config.h"
4
5// #define DODS_DEBUG
6
7#include "Ancillary.h"
8#include "debug.h"
9
10#ifndef WIN32
11#ifdef HAVE_UNISTD_H
12#include <unistd.h>
13#endif
14#else
15#include <fcntl.h>
16#include <io.h>
17#include <process.h>
18// Win32 does not define this. 08/21/02 jhrg
19#define F_OK 0
20#endif
21
22namespace libdap {
23
68string Ancillary::find_ancillary_file(const string &pathname, const string &ext, const string &dir,
69 const string &file) {
70 string::size_type slash = pathname.rfind('/') + 1;
71 string directory = pathname.substr(0, slash);
72 string filename = pathname.substr(slash);
73 string basename = pathname.substr(slash, pathname.rfind('.') - slash);
74
75 DBG(cerr << "find ancillary file params: " << pathname << ", " << ext << ", " << dir << ", " << file << endl);
76 DBG(cerr << "find ancillary file comp: " << directory << ", " << filename << ", " << basename << endl);
77
78 string dot_ext = "." + ext;
79
80 string name = directory + basename + dot_ext;
81 if (access(name.c_str(), F_OK) == 0)
82 return name;
83
84 name = pathname + dot_ext;
85 if (access(name.c_str(), F_OK) == 0)
86 return name;
87
88 name = directory + ext;
89 if (access(name.c_str(), F_OK) == 0)
90 return name;
91
92 name = dir + basename + dot_ext;
93 if (access(name.c_str(), F_OK) == 0)
94 return name;
95
96 name = directory + file + dot_ext;
97 if (access(name.c_str(), F_OK) == 0)
98 return name;
99
100 name = dir + file + dot_ext;
101 if (access(name.c_str(), F_OK) == 0)
102 return name;
103
104 name = dir + ext;
105 if (access(name.c_str(), F_OK) == 0)
106 return name;
107
108 return "";
109}
110
111// Given a pathname to a datafile, take that pathname apart and look for an
112// ancillary file that describes a group of datafiles of which this datafile
113// is a member. Assume that groups follow a simple naming convention where
114// files use either leading or trailing digits and a common basename to name
115// group members. For example, 00stuff.hdf, 01stuff.hdf, 02stuff.hdf, ..., is
116// a group and is has `stuff' as its basename.
117
131string Ancillary::find_group_ancillary_file(const string &name, const string &ext) {
132 // Given /usr/local/data/stuff.01.nc
133 // pathname = /usr/local/data, filename = stuff.01.nc and
134 // rootname = stuff.01
135 string::size_type slash = name.find_last_of('/');
136 string dirname = name.substr(0, slash);
137 string filename = name.substr(slash + 1);
138 string rootname = filename.substr(0, filename.find_last_of('.'));
139
140 // Instead of using regexs, scan the filename for leading and then
141 // trailing digits.
142 string::iterator rootname_iter = rootname.begin();
143 string::iterator rootname_end_iter = rootname.end();
144 if (isdigit(*rootname_iter)) {
145 while (rootname_iter != rootname_end_iter && isdigit(*++rootname_iter))
146 ;
147
148 // We want: new_name = dirname + "/" + <base> + ext but without
149 // creating a bunch of temp objects.
150 string new_name = dirname;
151 new_name.append("/");
152 new_name.append(rootname_iter, rootname_end_iter);
153 new_name.append(ext);
154 DBG(cerr << "New Name (iter): " << new_name << endl);
155 if (access(new_name.c_str(), F_OK) == 0) {
156 return new_name;
157 }
158 }
159
160 string::reverse_iterator rootname_riter = rootname.rbegin();
161 string::reverse_iterator rootname_end_riter = rootname.rend();
162 if (isdigit(*rootname_riter)) {
163 while (rootname_riter != rootname_end_riter && isdigit(*++rootname_riter))
164 ;
165 string new_name = dirname;
166 new_name.append("/");
167 // I used reverse iters to scan rootname backwards. To avoid
168 // reversing the fragment between end_riter and riter, pass append
169 // regular iters obtained using reverse_iterator::base(). See Meyers
170 // p. 123. 1/22/2002 jhrg
171 new_name.append(rootname_end_riter.base(), rootname_riter.base());
172 new_name.append(ext);
173 DBG(cerr << "New Name (riter): " << new_name << endl);
174 if (access(new_name.c_str(), F_OK) == 0) {
175 return new_name;
176 }
177 }
178
179 // If we're here either the file does not begin with leading digits or a
180 // template made by removing those digits was not found.
181
182 return "";
183}
184
185void Ancillary::read_ancillary_das(DAS &das, const string &pathname, const string &dir, const string &file) {
186 string name = find_ancillary_file(pathname, "das", dir, file);
187
188 DBG(cerr << "In Ancillary::read_ancillary_dds: name:" << name << endl);
189
190 FILE *in = fopen(name.c_str(), "r");
191 if (in) {
192 das.parse(in);
193 (void)fclose(in);
194 }
195}
196
197void Ancillary::read_ancillary_dds(DDS &dds, const string &pathname, const string &dir, const string &file) {
198 string name = find_ancillary_file(pathname, "dds", dir, file);
199
200 DBG(cerr << "In Ancillary::read_ancillary_dds: name:" << name << endl);
201
202 FILE *in = fopen(name.c_str(), "r");
203 if (in) {
204 dds.parse(in);
205 (void)fclose(in);
206 }
207}
208
209} // namespace libdap
static string find_group_ancillary_file(const string &pathname, const string &ext)
Definition Ancillary.cc:131
static void read_ancillary_das(DAS &das, const string &pathname, const string &dir="", const string &file="")
Definition Ancillary.cc:185
static void read_ancillary_dds(DDS &dds, const string &pathname, const string &dir="", const string &file="")
Definition Ancillary.cc:197
static string find_ancillary_file(const string &pathname, const string &ext, const string &dir, const string &file)
Find a file with ancillary data.
Definition Ancillary.cc:68
Hold attribute data for a DAP2 dataset.
Definition DAS.h:119
virtual void parse(string fname)
Reads a DAS from the named file.
Definition DAS.cc:213
void parse(string fname)
Parse a DDS from a file with the given d_name.
Definition DDS.cc:740
#define DBG(x)
Definition debug.h:58
top level DAP object to house generic methods
Definition AISConnect.cc:30