libdap++  Updated for version 3.14.0
util.cc
Go to the documentation of this file.
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
5 // Access Protocol.
6 
7 // Copyright (c) 2002,2003 OPeNDAP, Inc.
8 // Author: James Gallagher <jgallagher@opendap.org>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 
26 // (c) COPYRIGHT URI/MIT 1994-1999
27 // Please read the full copyright statement in the file COPYRIGHT_URI.
28 //
29 // Authors:
30 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
31 
32 // Utility functions used by the api.
33 //
34 // jhrg 9/21/94
35 
36 #include "config.h"
37 
38 #include <fstream>
39 
40 #include <cassert>
41 #include <cstring>
42 #include <climits>
43 
44 #include <ctype.h>
45 #ifndef TM_IN_SYS_TIME
46 #include <time.h>
47 #else
48 #include <sys/time.h>
49 #endif
50 
51 #ifndef WIN32
52 #include <unistd.h> // for stat
53 #else
54 #include <io.h>
55 #include <fcntl.h>
56 #include <process.h>
57 #endif
58 
59 #include <sys/types.h>
60 #include <sys/stat.h>
61 
62 #include <string>
63 #include <sstream>
64 #include <vector>
65 #include <algorithm>
66 #include <stdexcept>
67 
68 #include "BaseType.h"
69 #include "Byte.h"
70 #include "Int16.h"
71 #include "Int32.h"
72 #include "UInt16.h"
73 #include "UInt32.h"
74 #include "Float32.h"
75 #include "Float64.h"
76 #include "Str.h"
77 #include "Array.h"
78 
79 #include "Int64.h"
80 #include "UInt64.h"
81 #include "Int8.h"
82 
83 #include "Error.h"
84 
85 #include "util.h"
86 #include "GNURegex.h"
87 #include "debug.h"
88 
89 using namespace std;
90 
91 namespace libdap {
92 
95 {
96 #ifdef COMPUTE_ENDIAN_AT_RUNTIME
97 
98  dods_int16 i = 0x0100;
99  char *c = reinterpret_cast<char*>(&i);
100  return *c;
101 
102 #else
103 
104 #ifdef WORDS_BIGENDIAN
105  return true;
106 #else
107  return false;
108 #endif
109 
110 #endif
111 }
112 
120 {
121  assert(arg);
122 
123  if (arg->type() != dods_str_c)
124  throw Error(malformed_expr, "The function requires a string argument.");
125 
126  if (!arg->read_p())
127  throw InternalErr(__FILE__, __LINE__,
128  "The CE Evaluator built an argument list where some constants held no values.");
129 
130  return static_cast<Str*>(arg)->value();
131 }
132 
133 template<class T> static void set_array_using_double_helper(Array *a, double *src, int src_len)
134 {
135  assert(a);
136  assert(src);
137  assert(src_len > 0);
138 
139  vector<T> values(src_len);
140  for (int i = 0; i < src_len; ++i)
141  values[i] = (T) src[i];
142 
143  // This copie the values
144  a->set_value(values, src_len);
145 }
146 
167 void set_array_using_double(Array *dest, double *src, int src_len)
168 {
169  assert(dest);
170  assert(src);
171  assert(src_len > 0);
172 
173  // Simple types are Byte, ..., Float64, String and Url.
174  if ((dest->type() == dods_array_c && !dest->var()->is_simple_type())
175  || dest->var()->type() == dods_str_c
176  || dest->var()->type() == dods_url_c)
177  throw InternalErr(__FILE__, __LINE__,
178  "The function requires a numeric-type array argument.");
179 
180  // Test sizes. Note that Array::length() takes any constraint into account
181  // when it returns the length. Even if this was removed, the 'helper'
182  // function this uses calls Vector::val2buf() which uses Vector::width()
183  // which in turn uses length().
184  if (dest->length() != src_len)
185  throw InternalErr(__FILE__, __LINE__,
186  "The source and destination array sizes don't match ("
187  + long_to_string(src_len) + " versus "
188  + long_to_string(dest->length()) + ").");
189 
190  // The types of arguments that the CE Parser will build for numeric
191  // constants are limited to Uint32, Int32 and Float64. See ce_expr.y.
192  // Expanded to work for any numeric type so it can be used for more than
193  // just arguments.
194  switch (dest->var()->type()) {
195  case dods_byte_c:
196  set_array_using_double_helper<dods_byte>(dest, src, src_len);
197  break;
198  case dods_uint16_c:
199  set_array_using_double_helper<dods_uint16>(dest, src, src_len);
200  break;
201  case dods_int16_c:
202  set_array_using_double_helper<dods_int16>(dest, src, src_len);
203  break;
204  case dods_uint32_c:
205  set_array_using_double_helper<dods_uint32>(dest, src, src_len);
206  break;
207  case dods_int32_c:
208  set_array_using_double_helper<dods_int32>(dest, src, src_len);
209  break;
210  case dods_float32_c:
211  set_array_using_double_helper<dods_float32>(dest, src, src_len);
212  break;
213  case dods_float64_c:
214  set_array_using_double_helper<dods_float64>(dest, src, src_len);
215  break;
216 
217  // DAP4 support
218  case dods_uint8_c:
219  set_array_using_double_helper<dods_byte>(dest, src, src_len);
220  break;
221  case dods_int8_c:
222  set_array_using_double_helper<dods_int8>(dest, src, src_len);
223  break;
224  case dods_uint64_c:
225  set_array_using_double_helper<dods_uint64>(dest, src, src_len);
226  break;
227  case dods_int64_c:
228  set_array_using_double_helper<dods_int64>(dest, src, src_len);
229  break;
230  default:
231  throw InternalErr(__FILE__, __LINE__,
232  "The argument list built by the CE parser contained an unsupported numeric type.");
233  }
234 
235  // Set the read_p property.
236  dest->set_read_p(true);
237 }
238 
239 template<class T> static double *extract_double_array_helper(Array * a)
240 {
241  assert(a);
242 
243  int length = a->length();
244 
245  vector<T> b(length);
246  a->value(&b[0]); // Extract the values of 'a' to 'b'
247 
248  double *dest = new double[length];
249  for (int i = 0; i < length; ++i)
250  dest[i] = (double) b[i];
251 
252  return dest;
253 }
254 
266 {
267  assert(a);
268 
269  // Simple types are Byte, ..., Float64, String and Url.
270  if ((a->type() == dods_array_c && !a->var()->is_simple_type())
271  || a->var()->type() == dods_str_c || a->var()->type() == dods_url_c)
272  throw Error(malformed_expr,
273  "The function requires a DAP numeric-type array argument.");
274 
275  if (!a->read_p())
276  throw InternalErr(__FILE__, __LINE__,
277  string("The Array '") + a->name() +
278  "'does not contain values.");
279 
280  // The types of arguments that the CE Parser will build for numeric
281  // constants are limited to Uint32, Int32 and Float64. See ce_expr.y.
282  // Expanded to work for any numeric type so it can be used for more than
283  // just arguments.
284  switch (a->var()->type()) {
285  case dods_byte_c:
286  return extract_double_array_helper<dods_byte>(a);
287  case dods_uint16_c:
288  return extract_double_array_helper<dods_uint16>(a);
289  case dods_int16_c:
290  return extract_double_array_helper<dods_int16>(a);
291  case dods_uint32_c:
292  return extract_double_array_helper<dods_uint32>(a);
293  case dods_int32_c:
294  return extract_double_array_helper<dods_int32>(a);
295  case dods_float32_c:
296  return extract_double_array_helper<dods_float32>(a);
297  case dods_float64_c:
298  // Should not be copying these values, just read them,
299  // but older code may depend on the return of this function
300  // being something that should be deleted, so leave this
301  // alone. jhrg 2/24/15
302  return extract_double_array_helper<dods_float64>(a);
303 
304  // Support for DAP4
305  case dods_uint8_c:
306  return extract_double_array_helper<dods_byte>(a);
307  case dods_int8_c:
308  return extract_double_array_helper<dods_int8>(a);
309  case dods_uint64_c:
310  return extract_double_array_helper<dods_uint64>(a);
311  case dods_int64_c:
312  return extract_double_array_helper<dods_int64>(a);
313  default:
314  throw InternalErr(__FILE__, __LINE__,
315  "The argument list built by the CE parser contained an unsupported numeric type.");
316  }
317 }
318 
319 // This helper function assume 'dest' is the correct size. This should not
320 // be called when the Array 'a' is a Float64, since the values are already
321 // in a double array!
322 template<class T> static void extract_double_array_helper(Array * a, vector<double> &dest)
323 {
324  assert(a);
325  assert(dest.size() == (unsigned long)a->length());
326 
327  int length = a->length();
328 
329  vector<T> b(length);
330  a->value(&b[0]); // Extract the values of 'a' to 'b'
331 
332  for (int i = 0; i < length; ++i)
333  dest[i] = (double) b[i];
334 }
335 
347 void extract_double_array(Array *a, vector<double> &dest)
348 {
349  assert(a);
350 
351  // Simple types are Byte, ..., Float64, String and Url.
352  if ((a->type() == dods_array_c && !a->var()->is_simple_type())
353  || a->var()->type() == dods_str_c || a->var()->type() == dods_url_c)
354  throw Error(malformed_expr,
355  "The function requires a DAP numeric-type array argument.");
356 
357  if (!a->read_p())
358  throw InternalErr(__FILE__, __LINE__,
359  string("The Array '") + a->name() +
360  "'does not contain values.");
361 
362  dest.resize(a->length());
363 
364  // The types of arguments that the CE Parser will build for numeric
365  // constants are limited to Uint32, Int32 and Float64. See ce_expr.y.
366  // Expanded to work for any numeric type so it can be used for more than
367  // just arguments.
368  switch (a->var()->type()) {
369  case dods_byte_c:
370  return extract_double_array_helper<dods_byte>(a, dest);
371  case dods_uint16_c:
372  return extract_double_array_helper<dods_uint16>(a, dest);
373  case dods_int16_c:
374  return extract_double_array_helper<dods_int16>(a, dest);
375  case dods_uint32_c:
376  return extract_double_array_helper<dods_uint32>(a, dest);
377  case dods_int32_c:
378  return extract_double_array_helper<dods_int32>(a, dest);
379  case dods_float32_c:
380  return extract_double_array_helper<dods_float32>(a, dest);
381  case dods_float64_c:
382  return a->value(&dest[0]); // no need to copy the values
383  // return extract_double_array_helper<dods_float64>(a, dest);
384 
385  // Support for DAP4
386  case dods_uint8_c:
387  return extract_double_array_helper<dods_byte>(a, dest);
388  case dods_int8_c:
389  return extract_double_array_helper<dods_int8>(a, dest);
390  case dods_uint64_c:
391  return extract_double_array_helper<dods_uint64>(a, dest);
392  case dods_int64_c:
393  return extract_double_array_helper<dods_int64>(a, dest);
394  default:
395  throw InternalErr(__FILE__, __LINE__,
396  "The argument list built by the CE parser contained an unsupported numeric type.");
397  }
398 }
399 
410 {
411  assert(arg);
412 
413  // Simple types are Byte, ..., Float64, String and Url.
414  if (!arg->is_simple_type() || arg->type() == dods_str_c || arg->type() == dods_url_c)
415  throw Error(malformed_expr,
416  "The function requires a numeric-type argument.");
417 
418  if (!arg->read_p())
419  throw InternalErr(__FILE__, __LINE__,
420  "The Evaluator built an argument list where some constants held no values.");
421 
422  // The types of arguments that the CE Parser will build for numeric
423  // constants are limited to Uint32, Int32 and Float64. See ce_expr.y.
424  // Expanded to work for any numeric type so it can be used for more than
425  // just arguments.
426  switch (arg->type()) {
427  case dods_byte_c:
428  return (double)(static_cast<Byte*>(arg)->value());
429  case dods_uint16_c:
430  return (double)(static_cast<UInt16*>(arg)->value());
431  case dods_int16_c:
432  return (double)(static_cast<Int16*>(arg)->value());
433  case dods_uint32_c:
434  return (double)(static_cast<UInt32*>(arg)->value());
435  case dods_int32_c:
436  return (double)(static_cast<Int32*>(arg)->value());
437  case dods_float32_c:
438  return (double)(static_cast<Float32*>(arg)->value());
439  case dods_float64_c:
440  return static_cast<Float64*>(arg)->value();
441 
442  // Support for DAP4 types.
443  case dods_uint8_c:
444  return (double)(static_cast<Byte*>(arg)->value());
445  case dods_int8_c:
446  return (double)(static_cast<Int8*>(arg)->value());
447  case dods_uint64_c:
448  return (double)(static_cast<UInt64*>(arg)->value());
449  case dods_int64_c:
450  return (double)(static_cast<Int64*>(arg)->value());
451 
452  default:
453  throw InternalErr(__FILE__, __LINE__,
454  "The argument list built by the parser contained an unsupported numeric type.");
455  }
456 }
457 
458 // Remove spaces from the start of a URL and from the start of any constraint
459 // expression it contains. 4/7/98 jhrg
460 
467 string
468 prune_spaces(const string &name)
469 {
470  // If the URL does not even have white space return.
471  if (name.find_first_of(' ') == name.npos)
472  return name;
473  else {
474  // Strip leading spaces from http://...
475  unsigned int i = name.find_first_not_of(' ');
476  string tmp_name = name.substr(i);
477 
478  // Strip leading spaces from constraint part (following `?').
479  unsigned int j = tmp_name.find('?') + 1;
480  i = tmp_name.find_first_not_of(' ', j);
481  tmp_name.erase(j, i - j);
482 
483  return tmp_name;
484  }
485 }
486 
487 // Compare elements in a list of (BaseType *)s and return true if there are
488 // no duplicate elements, otherwise return false.
489 
490 bool
491 unique_names(vector<BaseType *> l, const string &var_name,
492  const string &type_name, string &msg)
493 {
494  // copy the identifier names to a vector
495  vector<string> names(l.size());
496 
497  int nelem = 0;
498  typedef std::vector<BaseType *>::const_iterator citer ;
499  for (citer i = l.begin(); i != l.end(); i++) {
500  assert(*i);
501  names[nelem++] = (*i)->name();
502  DBG(cerr << "NAMES[" << nelem - 1 << "]=" << names[nelem-1] << endl);
503  }
504 
505  // sort the array of names
506  sort(names.begin(), names.end());
507 
508  // sort the array of names
509  sort(names.begin(), names.end());
510 
511  // look for any instance of consecutive names that are ==
512  for (int j = 1; j < nelem; ++j) {
513  if (names[j-1] == names[j]) {
514  ostringstream oss;
515  oss << "The variable `" << names[j]
516  << "' is used more than once in " << type_name << " `"
517  << var_name << "'";
518  msg = oss.str();
519 
520  return false;
521  }
522  }
523 
524  return true;
525 }
526 
527 const char *
529 {
530  return LIBDAP_ROOT;
531 }
532 
537 extern "C" const char *
539 {
540  return PACKAGE_VERSION;
541 }
542 
543 extern "C" const char *
545 {
546  return PACKAGE_NAME;
547 }
548 
554 string
556 {
557  time_t TimBin;
558 
559  if (time(&TimBin) == (time_t) - 1)
560  return string("time() error");
561  else {
562  char *ctime_value = ctime(&TimBin);
563  if (ctime_value) {
564  string TimStr = ctime_value;
565  return TimStr.substr(0, TimStr.size() - 2); // remove the \n
566  }
567  else
568  return "Unknown";
569  }
570 }
571 
576 void
577 downcase(string &s)
578 {
579  for (unsigned int i = 0; i < s.length(); i++)
580  s[i] = tolower(s[i]);
581 }
582 
588 bool
589 is_quoted(const string &s)
590 {
591  return (!s.empty() && s[0] == '\"' && s[s.length()-1] == '\"');
592 }
593 
600 string
601 remove_quotes(const string &s)
602 {
603  if (is_quoted(s))
604  return s.substr(1, s.length() - 2);
605  else
606  return s;
607 }
608 
610 Type get_type(const char *name)
611 {
612  if (strcmp(name, "Byte") == 0)
613  return dods_byte_c;
614 
615  if (strcmp(name, "Char") == 0)
616  return dods_char_c;
617 
618  if (strcmp(name, "Int8") == 0)
619  return dods_int8_c;
620 
621  if (strcmp(name, "UInt8") == 0)
622  return dods_uint8_c;
623 
624  if (strcmp(name, "Int16") == 0)
625  return dods_int16_c;
626 
627  if (strcmp(name, "UInt16") == 0)
628  return dods_uint16_c;
629 
630  if (strcmp(name, "Int32") == 0)
631  return dods_int32_c;
632 
633  if (strcmp(name, "UInt32") == 0)
634  return dods_uint32_c;
635 
636  if (strcmp(name, "Int64") == 0)
637  return dods_int64_c;
638 
639  if (strcmp(name, "UInt64") == 0)
640  return dods_uint64_c;
641 
642  if (strcmp(name, "Float32") == 0)
643  return dods_float32_c;
644 
645  if (strcmp(name, "Float64") == 0)
646  return dods_float64_c;
647 
648  if (strcmp(name, "String") == 0)
649  return dods_str_c;
650 
651  // accept both spellings; this might be confusing since URL
652  // could be filtered through code and come out Url. Don't know...
653  // jhrg 8/15/13
654  if (strcmp(name, "Url") == 0 || strcmp(name, "URL") == 0)
655  return dods_url_c;
656 
657  if (strcmp(name, "Enum") == 0)
658  return dods_enum_c;
659 
660  if (strcmp(name, "Opaque") == 0)
661  return dods_opaque_c;
662 
663  if (strcmp(name, "Array") == 0)
664  return dods_array_c;
665 
666  if (strcmp(name, "Structure") == 0)
667  return dods_structure_c;
668 
669  if (strcmp(name, "Sequence") == 0)
670  return dods_sequence_c;
671 
672  if (strcmp(name, "Grid") == 0)
673  return dods_grid_c;
674 
675  return dods_null_c;
676 }
677 
685 string
687 {
688  switch (t) {
689  case dods_null_c:
690  return string("Null");
691  case dods_byte_c:
692  return string("Byte");
693  case dods_int16_c:
694  return string("Int16");
695  case dods_uint16_c:
696  return string("UInt16");
697  case dods_int32_c:
698  return string("Int32");
699  case dods_uint32_c:
700  return string("UInt32");
701  case dods_float32_c:
702  return string("Float32");
703  case dods_float64_c:
704  return string("Float64");
705  case dods_str_c:
706  return string("String");
707  case dods_url_c:
708  return string("Url");
709 
710  case dods_array_c:
711  return string("Array");
712  case dods_structure_c:
713  return string("Structure");
714  case dods_sequence_c:
715  return string("Sequence");
716  case dods_grid_c:
717  return string("Grid");
718 
719  default:
720  throw InternalErr(__FILE__, __LINE__, "Unknown type.");
721  }
722 }
723 
731 string
733 {
734  switch (t) {
735  case dods_null_c:
736  return string("Null");
737  case dods_byte_c:
738  return string("Byte");
739  case dods_char_c:
740  return string("Char");
741  case dods_int8_c:
742  return string("Int8");
743  case dods_uint8_c:
744  return string("UInt8");
745  case dods_int16_c:
746  return string("Int16");
747  case dods_uint16_c:
748  return string("UInt16");
749  case dods_int32_c:
750  return string("Int32");
751  case dods_uint32_c:
752  return string("UInt32");
753  case dods_int64_c:
754  return string("Int64");
755  case dods_uint64_c:
756  return string("UInt64");
757  case dods_enum_c:
758  return string("Enum");
759 
760  case dods_float32_c:
761  return string("Float32");
762  case dods_float64_c:
763  return string("Float64");
764 
765  case dods_str_c:
766  return string("String");
767  case dods_url_c:
768  return string("URL");
769 
770  case dods_opaque_c:
771  return string("Opaque");
772 
773  case dods_array_c:
774  return string("Array");
775 
776  case dods_structure_c:
777  return string("Structure");
778  case dods_sequence_c:
779  return string("Sequence");
780  case dods_group_c:
781  return string("Group");
782 
783  default:
784  throw InternalErr(__FILE__, __LINE__, "Unknown type.");
785  }
786 }
787 
798 string
800 {
801  try {
802  return D4type_name(t);
803  }
804  catch (...) {
805  return D2type_name(t);
806  }
807 }
808 
814 bool
816 {
817  switch (t) {
818 
819  case dods_byte_c:
820  case dods_char_c:
821 
822  case dods_int8_c:
823  case dods_uint8_c:
824 
825  case dods_int16_c:
826  case dods_uint16_c:
827  case dods_int32_c:
828  case dods_uint32_c:
829 
830  case dods_int64_c:
831  case dods_uint64_c:
832 
833  case dods_float32_c:
834  case dods_float64_c:
835  case dods_str_c:
836  case dods_url_c:
837  case dods_enum_c:
838  case dods_opaque_c:
839  return true;
840 
841  case dods_null_c:
842  case dods_array_c:
843  case dods_structure_c:
844  case dods_sequence_c:
845  case dods_grid_c:
846  case dods_group_c:
847  default:
848  return false;
849  }
850 
851  return false;
852 }
853 
857 bool
859 {
860  switch (t) {
861  case dods_null_c:
862  case dods_byte_c:
863  case dods_char_c:
864 
865  case dods_int8_c:
866  case dods_uint8_c:
867 
868  case dods_int16_c:
869  case dods_uint16_c:
870 
871  case dods_int32_c:
872  case dods_uint32_c:
873 
874  case dods_int64_c:
875  case dods_uint64_c:
876 
877  case dods_float32_c:
878  case dods_float64_c:
879 
880  case dods_str_c:
881  case dods_url_c:
882  case dods_enum_c:
883  case dods_opaque_c:
884  return false;
885 
886  case dods_array_c:
887  return true;
888 
889  case dods_structure_c:
890  case dods_sequence_c:
891  case dods_grid_c:
892  case dods_group_c:
893  default:
894  return false;
895  }
896 
897  return false;
898 }
899 
904 bool
906 {
907  switch (t) {
908  case dods_null_c:
909  case dods_byte_c:
910  case dods_char_c:
911 
912  case dods_int8_c:
913  case dods_uint8_c:
914 
915  case dods_int16_c:
916  case dods_uint16_c:
917  case dods_int32_c:
918  case dods_uint32_c:
919 
920  case dods_int64_c:
921  case dods_uint64_c:
922 
923  case dods_float32_c:
924  case dods_float64_c:
925  case dods_str_c:
926  case dods_url_c:
927  case dods_enum_c:
928  case dods_opaque_c:
929 
930  case dods_array_c:
931  return false;
932 
933  case dods_structure_c:
934  case dods_sequence_c:
935  case dods_grid_c:
936  case dods_group_c:
937  default:
938  return true;
939  }
940 
941  return false;
942 }
943 
949 {
950  switch (t) {
951  case dods_byte_c:
952  case dods_char_c:
953  case dods_int8_c:
954  case dods_uint8_c:
955  case dods_int16_c:
956  case dods_uint16_c:
957  case dods_int32_c:
958  case dods_uint32_c:
959  case dods_int64_c:
960  case dods_uint64_c:
961  return true;
962  default:
963  return false;
964  }
965 }
966 
973 bool
974 dir_exists(const string &dir)
975 {
976  struct stat buf;
977 
978  return (stat(dir.c_str(), &buf) == 0) && (buf.st_mode & S_IFDIR);
979 }
980 
981 // Jose Garcia
982 void
983 append_long_to_string(long val, int base, string &str_val)
984 {
985  // The array digits contains 36 elements which are the
986  // posible valid digits for out bases in the range
987  // [2,36]
988  char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
989  // result of val / base
990  ldiv_t r;
991 
992  if (base > 36 || base < 2) {
993  // no conversion if wrong base
994  std::invalid_argument ex("The parameter base has an invalid value.");
995  throw ex;
996  }
997  if (val < 0)
998  str_val += '-';
999  r = ldiv(labs(val), base);
1000 
1001  // output digits of val/base first
1002  if (r.quot > 0)
1003  append_long_to_string(r.quot, base, str_val);
1004 
1005  // output last digit
1006 
1007  str_val += digits[(int)r.rem];
1008 }
1009 
1010 // base defaults to 10
1011 string
1012 long_to_string(long val, int base)
1013 {
1014  string s;
1015  append_long_to_string(val, base, s);
1016  return s;
1017 }
1018 
1019 // Jose Garcia
1020 void append_double_to_string(const double &num, string &str)
1021 {
1022  // s having 100 characters should be enough for sprintf to do its job.
1023  // I want to banish all instances of sprintf. 10/5/2001 jhrg
1024  ostringstream oss;
1025  oss.precision(9);
1026  oss << num;
1027  str += oss.str();
1028 }
1029 
1030 string
1031 double_to_string(const double &num)
1032 {
1033  string s;
1034  append_double_to_string(num, s);
1035  return s;
1036 }
1037 
1038 // Given a pathname, return the file at the end of the path. This is used
1039 // when reporting errors (maybe other times, too) to keep the server from
1040 // revealing too much about its organization when sending error responses
1041 // back to clients. 10/11/2000 jhrg
1042 // MT-safe. 08/05/02 jhrg
1043 
1044 #ifdef WIN32
1045 static const char path_sep[] =
1046  {"\\"
1047  };
1048 #else
1049 static const char path_sep[] =
1050  {"/"
1051  };
1052 #endif
1053 
1062 string
1063 path_to_filename(string path)
1064 {
1065  string::size_type pos = path.rfind(path_sep);
1066 
1067  return (pos == string::npos) ? path : path.substr(++pos);
1068 }
1069 
1070 #define CHECK_BIT( tab, bit ) ( tab[ (bit)/8 ] & (1<<( (bit)%8 )) )
1071 #define BITLISTSIZE 16 /* bytes used for [chars] in compiled expr */
1072 
1073 /*
1074  * globchars() - build a bitlist to check for character group match
1075  */
1076 
1077 static void globchars(const char *s, const char *e, char *b) {
1078  int neg = 0;
1079 
1080  memset(b, '\0', BITLISTSIZE);
1081 
1082  if (*s == '^')
1083  neg++, s++;
1084 
1085  while (s < e) {
1086  int c;
1087 
1088  if (s + 2 < e && s[1] == '-') {
1089  for (c = s[0]; c <= s[2]; c++)
1090  b[c / 8] |= (1 << (c % 8));
1091  s += 3;
1092  }
1093  else {
1094  c = *s++;
1095  b[c / 8] |= (1 << (c % 8));
1096  }
1097  }
1098 
1099  if (neg) {
1100  int i;
1101  for (i = 0; i < BITLISTSIZE; i++)
1102  b[i] ^= 0377;
1103  }
1104 
1105  /* Don't include \0 in either $[chars] or $[^chars] */
1106 
1107  b[0] &= 0376;
1108 }
1109 
1126 int
1127 glob(const char *c, const char *s)
1128 {
1129  if (!c || !s)
1130  return 1;
1131 
1132  char bitlist[BITLISTSIZE];
1133  int i = 0;
1134  for (;;) {
1135  ++i;
1136  switch (*c++) {
1137  case '\0':
1138  return *s ? -1 : 0;
1139 
1140  case '?':
1141  if (!*s++)
1142  return i/*1*/;
1143  break;
1144 
1145  case '[': {
1146  /* scan for matching ] */
1147 
1148  const char *here = c;
1149  do {
1150  if (!*c++)
1151  return i/*1*/;
1152  } while (here == c || *c != ']');
1153  c++;
1154 
1155  /* build character class bitlist */
1156 
1157  globchars(here, c, bitlist);
1158 
1159  if (!CHECK_BIT( bitlist, *(unsigned char *)s ))
1160  return i/*1*/;
1161  s++;
1162  break;
1163  }
1164 
1165  case '*': {
1166  const char *here = s;
1167 
1168  while (*s)
1169  s++;
1170 
1171  /* Try to match the rest of the pattern in a recursive */
1172  /* call. If the match fails we'll back up chars, retrying. */
1173 
1174  while (s != here) {
1175  int r;
1176 
1177  /* A fast path for the last token in a pattern */
1178 
1179  r = *c ? glob(c, s) : *s ? -1 : 0;
1180 
1181  if (!r)
1182  return 0;
1183  else if (r < 0)
1184  return i/*1*/;
1185 
1186  --s;
1187  }
1188  break;
1189  }
1190 
1191  case '\\':
1192  /* Force literal match of next char. */
1193 
1194  if (!*c || *s++ != *c++)
1195  return i/*1*/;
1196  break;
1197 
1198  default:
1199  if (*s++ != c[-1])
1200  return i/*1*/;
1201  break;
1202  }
1203  }
1204 
1205  return 1; // Should never get here; this quiets gcc's warning
1206 }
1207 
1210 
1216 bool
1217 size_ok(unsigned int sz, unsigned int nelem)
1218 {
1219  return (sz > 0 && nelem < UINT_MAX / sz);
1220 }
1221 
1238 bool
1239 pathname_ok(const string &path, bool strict)
1240 {
1241  if (path.length() > 255)
1242  return false;
1243 
1244  Regex name("[-0-9A-z_./]+");
1245  if (!strict)
1246  name = "[:print:]+";
1247 
1248  string::size_type len = path.length();
1249  int result = name.match(path.c_str(), len);
1250  // Protect against casting too big an uint to int
1251  // if LEN is bigger than the max int32, the second test can't work
1252  if (len > INT_MAX || result != static_cast<int>(len))
1253  return false;
1254 
1255  return true;
1256 }
1257 
1259 
1264 string
1266 {
1267  return (string)"OPeNDAP DAP/" + libdap_version() + ": compiled on " + __DATE__ + ":" + __TIME__ ;
1268 }
1269 
1270 } // namespace libdap
1271 
Holds an 8-bit signed integer value.
Definition: Int8.h:42
Holds a64-bit signed integer.
Definition: Int64.h:49
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:421
Type get_type(const char *name)
Definition: util.cc:610
void downcase(string &s)
Definition: util.cc:577
bool is_constructor_type(Type t)
Returns true if the instance is a constructor (i.e., Structure, Sequence or Grid) type variable...
Definition: util.cc:905
#define malformed_expr
Definition: Error.h:64
string prune_spaces(const string &name)
Definition: util.cc:468
virtual int length() const
Definition: Vector.cc:513
Holds an unsigned 16-bit integer.
Definition: UInt16.h:57
virtual void set_read_p(bool state)
Indicates that the data is ready to send.
Definition: Vector.cc:362
string extract_string_argument(BaseType *arg)
Definition: util.cc:119
bool dir_exists(const string &dir)
Definition: util.cc:974
bool size_ok(unsigned int sz, unsigned int nelem)
sanitize the size of an array. Test for integer overflow when dynamically allocating an array...
Definition: util.cc:1217
bool is_vector_type(Type t)
Returns true if the instance is a vector (i.e., array) type variable.
Definition: util.cc:858
Type
Identifies the data type.
Definition: Type.h:94
Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:306
Holds a 32-bit floating point value.
Definition: Float32.h:61
A class for software fault reporting.
Definition: InternalErr.h:64
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Definition: Vector.cc:387
Holds character string data.
Definition: Str.h:62
void set_array_using_double(Array *dest, double *src, int src_len)
Definition: util.cc:167
#define DBG(x)
Definition: debug.h:58
bool pathname_ok(const string &path, bool strict)
Does the string name a potentially valid pathname? Test the given pathname to verify that it is a val...
Definition: util.cc:1239
#define PACKAGE_NAME
Definition: config.h:794
Holds a 16-bit signed integer value.
Definition: Int16.h:59
string D4type_name(Type t)
Returns the type of the class instance as a string. Supports all DAP4 types and not the DAP2-only typ...
Definition: util.cc:732
string path_to_filename(string path)
Definition: util.cc:1063
bool is_quoted(const string &s)
Definition: util.cc:589
bool is_simple_type(Type t)
Returns true if the instance is a numeric, string or URL type variable.
Definition: util.cc:815
string systime()
Definition: util.cc:555
const char * libdap_root()
Definition: util.cc:528
Holds a 64-bit unsigned integer.
Definition: UInt64.h:49
void append_long_to_string(long val, int base, string &str_val)
Definition: util.cc:983
double extract_double_value(BaseType *arg)
Definition: util.cc:409
string name() const
Returns the name of the class instance.
Definition: BaseType.cc:261
void extract_double_array(Array *a, vector< double > &dest)
Definition: util.cc:347
string long_to_string(long val, int base)
Definition: util.cc:1012
#define CHECK_BIT(tab, bit)
Definition: util.cc:1070
string dap_version()
Definition: util.cc:1265
string double_to_string(const double &num)
Definition: util.cc:1031
virtual bool is_simple_type() const
Returns true if the instance is a numeric, string or URL type variable.
Definition: BaseType.cc:334
string remove_quotes(const string &s)
Definition: util.cc:601
int16_t dods_int16
The basic data type for the DODS DAP types.
Definition: BaseType.h:117
string D2type_name(Type t)
Returns the type of the class instance as a string. Supports all DAP2 types and not the DAP4-only typ...
Definition: util.cc:686
#define LIBDAP_ROOT
Definition: config.h:764
Holds a 64-bit (double precision) floating point value.
Definition: Float64.h:60
Holds a single byte.
Definition: Byte.h:60
bool unique_names(vector< BaseType * > l, const string &var_name, const string &type_name, string &msg)
Definition: util.cc:491
#define PACKAGE_VERSION
Definition: config.h:806
A class for error processing.
Definition: Error.h:90
bool is_host_big_endian()
Does this host use big-endian byte order?
Definition: util.cc:94
Holds a 32-bit unsigned integer.
Definition: UInt32.h:59
string type_name(Type t)
Definition: util.cc:799
const char * libdap_version()
Definition: util.cc:538
A multidimensional array of identical data types.
Definition: Array.h:112
#define BITLISTSIZE
Definition: util.cc:1071
int glob(const char *c, const char *s)
Definition: util.cc:1127
bool is_integer_type(Type t)
Definition: util.cc:948
Holds a 32-bit signed integer.
Definition: Int32.h:65
void append_double_to_string(const double &num, string &str)
Definition: util.cc:1020
const char * libdap_name()
Definition: util.cc:544