Line data Source code
1 : #ifndef MISC_H
2 : #define MISC_H
3 : /*
4 : * ALMA - Atacama Large Millimeter Array
5 : * (c) European Southern Observatory, 2002
6 : * (c) Associated Universities Inc., 2002
7 : * Copyright by ESO (in the framework of the ALMA collaboration),
8 : * Copyright by AUI (in the framework of the ALMA collaboration),
9 : * All rights reserved.
10 : *
11 : * This library is free software; you can redistribute it and/or
12 : * modify it under the terms of the GNU Lesser General Public
13 : * License as published by the Free software Foundation; either
14 : * version 2.1 of the License, or (at your option) any later verson.
15 : *
16 : * This library is distributed in the hope that it will be useful,
17 : * but WITHOUT ANY WARRANTY, without even the implied warranty of
18 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 : * Lesser General Public License for more details.
20 : *
21 : * You should have received a copy of the GNU Lesser General Public
22 : * License along with this library; if not, write to the Free Software
23 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 : * MA 02111-1307 USA
25 : *
26 : *
27 : * File Misc.h
28 : */
29 :
30 : #include <iostream>
31 : #include <fstream>
32 : #include <string>
33 : #include <vector>
34 : #include <set>
35 : #include <map>
36 :
37 : #ifndef WITHOUT_BOOST
38 : #include <boost/filesystem/path.hpp>
39 : #include <boost/filesystem/convenience.hpp>
40 : #include <boost/algorithm/string/trim.hpp>
41 : #include <boost/algorithm/string/predicate.hpp>
42 : #include <boost/algorithm/string/split.hpp>
43 : #else
44 : #include <sys/stat.h>
45 : #include <sstream>
46 : #endif
47 :
48 : #include <algorithm>
49 : #include <cctype>
50 : #include <locale>
51 :
52 : typedef unsigned char xmlChar;
53 :
54 : struct _xmlNode;
55 : typedef struct _xmlNode xmlNode;
56 : typedef xmlNode *xmlNodePtr;
57 :
58 : struct _xmlDoc;
59 : typedef struct _xmlDoc xmlDoc;
60 : typedef xmlDoc *xmlDocPtr;
61 :
62 : struct _xsltStylesheet;
63 : typedef struct _xsltStylesheet xsltStylesheet;
64 : typedef xsltStylesheet *xsltStylesheetPtr;
65 :
66 : extern "C" int xmlLoadExtDtdDefaultValue;
67 :
68 : namespace asdm {
69 : /**
70 : * Some utility methods to manipulate directories.
71 : */
72 :
73 : /**
74 : * Returns whether the specified directory exists.
75 : *
76 : * Example:
77 : * --------
78 : * if (!directoryExists("output"))
79 : * {
80 : * createDirectory("output");
81 : * }
82 : */
83 : bool directoryExists(const char* dir);
84 :
85 : /**
86 : * Creates the specified directory. Fails if the path leading to
87 : * this directory does not exist.
88 : *
89 : * Example:
90 : * --------
91 : * createDirectory("output");
92 : */
93 : bool createDirectory(const char* dir);
94 :
95 : /**
96 : * Creates a complete path.
97 : *
98 : * Example:
99 : * --------
100 : * ("output/sample1/temperature0/");
101 : */
102 : bool createPath(const char* path);
103 :
104 :
105 : /**
106 : * Swap bytes
107 : */
108 : #define ByteSwap5(x) ByteSwap((unsigned char *) &x,sizeof(x))
109 : void ByteSwap(unsigned char * b, int n);
110 :
111 : /**
112 : * A class to represent byte order information.
113 : *
114 : */
115 : class ByteOrder {
116 : public:
117 : static const ByteOrder* Little_Endian; /*< A unique object to represent a little endian byte order. */
118 : static const ByteOrder* Big_Endian; /*< A unique object to represent a big endian byte order. */
119 : static const ByteOrder* Machine_Endianity; /*< A unique object storing the endianity of the machine. */
120 :
121 : /**
122 : * Returns a string representation of this.
123 : *
124 : * <ul>
125 : * <li> Little_Endian is returned as "Little_Endian", </li>
126 : * <li> Big_Endian is returned as "Big_Endian", </li>
127 : * </ul>
128 : */
129 : std::string toString() const ;
130 :
131 : /**
132 : * Convert a string to a const ByteOrder*.
133 : *
134 : * @param s the input string.
135 : * @return a const pointer to a ByteOrder for which the toString() method returns
136 : * a string == to the input string, or 0 if no such instance of ByteOrder exists.
137 : */
138 : static const ByteOrder* fromString(const std::string & s);
139 :
140 : private:
141 : std::string name_;
142 :
143 : ByteOrder(const std::string & name);
144 : virtual ~ByteOrder();
145 : static const ByteOrder* machineEndianity();
146 : };
147 :
148 : /**
149 : * Return a string whose content is equal to the content of s
150 : * but with all the repetitions of '/' characters replaced by
151 : * a unique '/'.
152 : *
153 : * @return a string.
154 : */
155 : std::string uniqSlashes(const std::string& s);
156 :
157 :
158 : #ifdef WITHOUT_BOOST
159 : // string trimming functions to be used in place of boost functions
160 : // uses lambdas (c++11)
161 :
162 : // trim from start (in place)
163 0 : inline void ltrim(std::string &s) {
164 0 : s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
165 0 : return !std::isspace(ch);
166 : }));
167 0 : }
168 :
169 : // trim from end (in place)
170 0 : inline void rtrim(std::string &s) {
171 0 : s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
172 0 : return !std::isspace(ch);
173 0 : }).base(), s.end());
174 0 : }
175 :
176 : // trim from both ends (in place)
177 0 : inline void trim(std::string &s) {
178 0 : ltrim(s);
179 0 : rtrim(s);
180 0 : }
181 :
182 : // trim from start (copying)
183 : inline std::string ltrim_copy(std::string s) {
184 : ltrim(s);
185 : return s;
186 : }
187 :
188 : // trim from end (copying)
189 : inline std::string rtrim_copy(std::string s) {
190 : rtrim(s);
191 : return s;
192 : }
193 :
194 : // trim from both ends (copying)
195 0 : inline std::string trim_copy(std::string s) {
196 0 : trim(s);
197 0 : return s;
198 : }
199 :
200 : // return a copy of str with everything transformed to upper case
201 0 : inline std::string str_toupper(std::string s) {
202 0 : std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::toupper(c); });
203 0 : return s;
204 : }
205 :
206 : // return a copy of str with everything transformed to lower case
207 : inline std::string str_tolower(std::string s) {
208 : std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); });
209 : return s;
210 : }
211 :
212 : // split a string into vector using provided character as the delimiter
213 : // resuls are added to the pre-existing results vector
214 0 : inline void strsplit(const std::string &str, char delim, std::vector<std::string> &result) {
215 0 : std::stringstream ss(str);
216 0 : std::string token;
217 0 : while(std::getline(ss,token,delim)) {
218 0 : result.push_back(token);
219 : }
220 0 : }
221 :
222 : // check to see if a file exists using posix 'stat(...)'
223 0 : inline bool file_exists(const std::string &filename) {
224 : struct stat statbuf;
225 0 : return (stat(filename.c_str(),&statbuf)==0);
226 : }
227 :
228 : #endif
229 :
230 : class ASDMUtilsException {
231 : public:
232 : ASDMUtilsException();
233 : ASDMUtilsException(const std::string& message);
234 :
235 : const std::string& getMessage() const;
236 :
237 : private:
238 : std::string message;
239 : };
240 :
241 : class ASDMUtils {
242 : public :
243 : enum Origin { UNKNOWN, ALMA, EVLA };
244 : static std::string version (const std::string& asdmPath);
245 : static std::vector<std::string> telescopeNames(const std::string& asdmPath);
246 : static Origin origin(const std::vector<std::string>& telescopeNames);
247 : static std::vector<std::string> xmlFilenames(const std::string& asdmPath);
248 :
249 : static std::string pathToV2V3ALMAxslTransform() ;
250 : static std::string pathToV2V3EVLAxslTransform() ;
251 : static std::string nameOfV2V3xslTransform(ASDMUtils::Origin origin);
252 :
253 : #ifndef WITHOUT_BOOST
254 : struct DotXMLFilter {
255 : public:
256 : DotXMLFilter(std::vector<std::string>& filenames);
257 : //void operator() (path& p);
258 : void operator() ( boost::filesystem::directory_entry& p);
259 : private:
260 : std::vector<std::string>* filenames;
261 : };
262 : #endif
263 :
264 : private :
265 : static bool initialize();
266 : static bool initialized;
267 : static bool hasChild(xmlDocPtr, xmlNodePtr node, const xmlChar* childName);
268 : static std::string parseRow(xmlDocPtr, xmlNodePtr node, const xmlChar* childName);
269 : static std::set<std::string> evlaValidNames;
270 : static std::set<std::string> almaValidNames;
271 : static std::map<ASDMUtils::Origin, std::string> filenameOfV2V3xslTransform;
272 : static std::map<std::string, std::string> rootSubdir ;
273 :
274 : static std::string pathToxslTransform( const std::string& xsltFilename);
275 : }; // end class ASDMUtil.
276 :
277 :
278 : /**
279 : * A class to define a collection of options regarding the way to consider an ASDM dataset
280 : * especially when it's about to be read on disk, parsed and transformed into its representation in memory.
281 : *
282 : *
283 : * The options that can be set with instances of this class are :
284 : * <ul>
285 : * <li> The origin of the dataset , i.e. the location where it's been produced. Currently three locations are known : ALMA, EVLA and IRAM at
286 : * its Plateau de Bure.</li>
287 : * <li> The version of the dataset. At present time version 2 or version 3 are known.</li>
288 : * <li> The fact that all the tables of a dataset are expected to be present in memory or only those which are referenced by the code
289 : * which needs to acces them </li>
290 : * </ul>
291 : * The method setFromFile defined in the class ASDM is the principal (not to say only) user of instances of this class.
292 : *
293 : * It should be noticed that all the methods defined to set the options return a reference onto the instance of ASDMParseOptions they
294 : * are applied. This technique facilitates the definition of a collection of options in one single statement, e.g. :
295 : *
296 : * <code>
297 : * ASDMParseOptions parse;
298 : * parse.asALMA().asV2().loadTablesOnDemand(true);
299 : * </code>
300 : *
301 : */
302 :
303 : class ASDMParseOptions {
304 : friend class ASDM;
305 :
306 : public:
307 : /**
308 : * A null constructor.
309 : *
310 : * The instance built by this constructor defines the instances as follows :
311 : * <ul>
312 : * <li> The origin is UNKNOWN. </li>
313 : * <li> The version is UNKNOWN. </li>
314 : * <li> All the tables are to be loaded in memory. </li>
315 : * </ul>
316 : *
317 : */
318 : ASDMParseOptions();
319 :
320 : /**
321 : * A copy constructor
322 : */
323 : ASDMParseOptions(const ASDMParseOptions& x);
324 :
325 : /**
326 : * The destructor.
327 : * Does nothing special.
328 : */
329 : virtual ~ASDMParseOptions();
330 :
331 : /**
332 : * = operator.
333 : */
334 : ASDMParseOptions & operator=(const ASDMParseOptions & rhs);
335 :
336 :
337 : /**
338 : * This is an ALMA dataset.
339 : */
340 : ASDMParseOptions& asALMA();
341 :
342 : /**
343 : * This is an IRAM / Plateau de Bure dataset.
344 : */
345 : ASDMParseOptions& asIRAM_PDB();
346 :
347 : /**
348 : * This is an EVLA dataset.
349 : */
350 : ASDMParseOptions& asEVLA();
351 :
352 : /**
353 : * This is a V2 dataset.
354 : */
355 : ASDMParseOptions& asV2();
356 :
357 : /**
358 : * This is a V3 dataset.
359 : */
360 : ASDMParseOptions& asV3();
361 :
362 : /**
363 : * Load all the tables in memory or only those which are required by the code.
364 : *
365 : * @param b a boolean value. <code>true</code> <-> load only the table which are required by the code when they are referred, <code>false</code> <-> load
366 : * all the code.
367 : */
368 : ASDMParseOptions& loadTablesOnDemand(bool b);
369 :
370 : /**
371 : * Determines if a control of the uniqueness is performed (b==true) or not (b==false) for each row of each table converted and loaded into memory.
372 : *
373 : * @param bool b
374 : *
375 : */
376 : ASDMParseOptions& checkRowUniqueness(bool b);
377 :
378 : /**
379 : * Defines how an instance of ASDMParseOptions is output on an ostream.
380 : */
381 : friend std::ostream& operator<<(std::ostream& output, const ASDMParseOptions& p);
382 :
383 : std::string toString() const;
384 :
385 : private:
386 : ASDMUtils::Origin origin_;
387 : bool detectOrigin_;
388 : std::string version_;
389 : bool detectVersion_;
390 : bool loadTablesOnDemand_;
391 : bool checkRowUniqueness_;
392 : }; // end class ASDMParseOptions.
393 :
394 : /**
395 : * A class to represent an exception thrown while an XSL transformation is applied by an instance of XSLTransformer.
396 : */
397 :
398 : class XSLTransformerException {
399 :
400 : public:
401 : /**
402 : * An empty constructor.
403 : */
404 : XSLTransformerException();
405 :
406 : /**
407 : * A constructor with a message associated with the exception.
408 : * @param m a string containing the message.
409 : */
410 : XSLTransformerException(const std::string & m);
411 :
412 : /**
413 : * The destructor.
414 : */
415 : virtual ~XSLTransformerException();
416 :
417 : /**
418 : * Return the message associated to this exception.
419 : * @return a string.
420 : */
421 : std::string getMessage() const;
422 :
423 : protected:
424 : std::string message;
425 :
426 : };
427 :
428 : inline XSLTransformerException::XSLTransformerException() : message ("XSLTransformerException") {}
429 0 : inline XSLTransformerException::XSLTransformerException(const std::string& m) : message(m) {}
430 0 : inline XSLTransformerException::~XSLTransformerException() {}
431 0 : inline std::string XSLTransformerException::getMessage() const {
432 0 : return "XSLTransformerException : " + message;
433 : }
434 :
435 : /**
436 : * A class to apply XSL transformations on an XML document.
437 : * The XSL transformation to be applied is defined when an instance is constructed. The class has its operator operator() overloaded
438 : * so that the transformation can be applied by using the instance as a functor.
439 : *
440 : * An instance built with an empty constructor will be interpreted as a "neutral" transformation, i.e. a transformation which leaves
441 : * the XML document unchanged.
442 : *
443 : */
444 : class XSLTransformer {
445 : public:
446 : /**
447 : * The empty constructor.
448 : *
449 : * The instance will leave the XML document unchanged.
450 : */
451 : XSLTransformer();
452 :
453 : /**
454 : * The destructor.
455 : */
456 : virtual ~XSLTransformer();
457 :
458 : /**
459 : * A constructor with an XSL transformation.
460 : *
461 : * The XSL transformation is read in the file whose path is passed as a parameter, then it's parsed
462 : * and stored in memory.
463 : *
464 : * @param xslPath the path ot the file containing the XSL transformation.
465 : * @throws XSLTransformerException;
466 : */
467 : XSLTransformer(const std::string& xsltPath);
468 :
469 : /**
470 : * A setter to (re) define the XSL transformation associated with the instance of XSLTransformer.
471 : *
472 : * The XSL transformation is read in the file whose path is passed as a parameter, then it's parsed
473 : * and stored in memory.
474 : *
475 : * @param xslPath the path ot the file containing the XSL transformation.
476 : *
477 : * @throws XSLTransformerException.
478 : */
479 : void setTransformation(const std::string& xsltPath);
480 :
481 : /**
482 : * Overloads operator() so that the instance can be used as a functor to apply the transformation on a given XML document.
483 : *
484 : * The XML document to be transformed is expected to be found in a file whose path is passed as a parameter.
485 : * It is read and parsed and stored into memory, then the XSL transformation associated with the instance is applied to the XML document
486 : * stored in memory and finally the result of the transformation is converted to a string which is returned to the caller.
487 : *
488 : * @param xsltPath a string whose value is the path to the file containing the XML document to be transformed.
489 : * @return a string containing the result of the transformation applied to the XML document.
490 : *
491 : * @throws XSLTransformerException.
492 : *
493 : */
494 : std::string operator()(const std::string& xmlPath);
495 :
496 : private:
497 :
498 : xsltStylesheetPtr cur;
499 :
500 : XSLTransformer& operator=(const XSLTransformer & rhs);
501 : XSLTransformer(const XSLTransformer & rsh);
502 : }; // end class XSLTransformer.
503 :
504 :
505 : /**
506 : * Functor class of for a comparison between a "given" character and a characted assumed to be read from a file.
507 : *
508 : * Instances of this class are meant to be used as binary bool functor comparing the uppercase version of the first (char) operand
509 : * with the second (char) operand and returning the boolan result of the comparison as long as the read head position in
510 : * the file passed as a parameter to the constructor is smaller than a limit also passed a parameter to the constructor. Once this
511 : * limit is passed , the () operator which returns the result of the comparison will return systematically true.
512 : *
513 : */
514 : class CharComparator {
515 : public:
516 : CharComparator(std::ifstream * is_p = NULL, off_t limit = 0);
517 : bool operator() (char cl, char cr);
518 :
519 : private:
520 : std::ifstream* is_p;
521 : off_t limit;
522 : char* asdmDebug_p;
523 : };
524 :
525 : /**
526 : * Functor class of for a comparison between a "given" character and a characted assumed to be read in a file with a an accumulation
527 : * of the characters read in the file into a accumulating string.
528 : *
529 : * Instances of this class are meant to be used as binary bool functor comparing the uppercase version of the first (char) operand
530 : * with the second (char) operand and returning the boolan result of the comparison as long as the read head position in
531 : * the file passed as a parameter to the constructor is smaller than a limit also passed a parameter to the constructor. Once this
532 : * limit is passed , the () operator which returns the result of the comparison will return systematically true. When the comparison
533 : * returns false, the character read from the file is appended to one string whose pointer is passed as a parameter to the constructor.
534 : *
535 : */
536 :
537 : class CharCompAccumulator {
538 : private:
539 : std::string* accumulator_p;
540 : std::ifstream* is_p;
541 : off_t limit;
542 : int nEqualChars;
543 : char* asdmDebug_p;
544 : public:
545 : /**
546 : * The constructor.
547 : *
548 : * @param accumulator_p a pointer to a string where the characters will be accumulated as a side effect of the call to the operator ().
549 : * @param is_p a pointer to the file where the characters are assumed to be read.
550 : * @param limit the position in the file beyond which the comparison will return systematically true.
551 : */
552 : CharCompAccumulator(std::string* accumulator_p = NULL, std::ifstream * is_p = NULL , off_t limit = 0);
553 :
554 : /**
555 : * Returns true when tpupper(cl) is equal to cr or when the read head position in is_p is >= limit.
556 : * @return a boolean
557 : *
558 : * Side effect : append cl to *accumulator when the result of the comparison is false.
559 : */
560 : bool operator()(char cl, char cr);
561 : };
562 : } // end namespace asdm
563 : #endif // MISC_H
564 :
|