File: Ancillary.cc

package info (click to toggle)
libdap 3.20.11-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 24,568 kB
  • sloc: cpp: 50,809; sh: 41,536; xml: 23,511; ansic: 20,030; yacc: 2,508; exp: 1,544; makefile: 990; lex: 309; perl: 52; fortran: 8
file content (230 lines) | stat: -rw-r--r-- 7,406 bytes parent folder | download
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