libdap++ Updated for version 3.8.2
|
00001 00002 // -*- mode: c++; c-basic-offset:4 -*- 00003 00004 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 00005 // Access Protocol. 00006 00007 // Copyright (c) 2002,2003 OPeNDAP, Inc. 00008 // Author: James Gallagher <jgallagher@opendap.org> 00009 // 00010 // This library is free software; you can redistribute it and/or 00011 // modify it under the terms of the GNU Lesser General Public 00012 // License as published by the Free Software Foundation; either 00013 // version 2.1 of the License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00023 // 00024 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00025 00026 // (c) COPYRIGHT URI/MIT 1995-1999 00027 // Please read the full copyright statement in the file COPYRIGHT_URI. 00028 // 00029 // Authors: 00030 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu> 00031 00032 // These functions are utility functions used by the various DAP parsers (the 00033 // DAS, DDS and constraint expression parsers). 00034 // jhrg 9/7/95 00035 00036 #include "config.h" 00037 00038 static char rcsid[] not_used = 00039 { "$Id: parser-util.cc 18315 2008-03-03 20:14:44Z jimg $" 00040 }; 00041 00042 #include <cerrno> 00043 #include <cassert> 00044 #include <cstring> 00045 #include <cmath> 00046 #include <iostream> 00047 #include <sstream> 00048 00049 // We wrap VC++ 6.x strtod() to account for a short comming 00050 // in that function in regards to "NaN". 00051 #ifdef WIN32 00052 #include <limits> 00053 double w32strtod(const char *, char **); 00054 #endif 00055 00056 #include "debug.h" 00057 #include "parser.h" // defines constants such as ID_MAX 00058 #include "dods-limits.h" 00059 #include "util.h" // Jose Garcia: for append_long_to_string. 00060 00061 using std::cerr; 00062 using std::endl; 00063 00064 #ifdef WIN32 00065 // VC++ 6.x strtod() doesn't recognize "NaN". Account for it 00066 // by wrapping it around a check for the Nan string. Use of 00067 // the product is obsolete as of 1/2007, but it is unknown if 00068 // the issue is still there in later releases of that product. 00069 // ROM - 01/2007 00070 double w32strtod(const char *val, char **ptr) 00071 { 00072 // Convert the two char arrays to compare to strings. 00073 string *sval = new string(val); 00074 string *snan = new string("NaN"); 00075 00076 // If val doesn't contain "NaN|Nan|nan|etc", use strtod as 00077 // provided. 00078 if (stricmp(sval->c_str(), snan->c_str()) != 0) 00079 return (strtod(val, ptr)); 00080 00081 // But if it does, return the bit pattern for Nan and point 00082 // the parsing ptr arg at the trailing '\0'. 00083 *ptr = (char *) val + strlen(val); 00084 return (std::numeric_limits < double >::quiet_NaN()); 00085 } 00086 #endif 00087 00088 namespace libdap { 00089 00090 // Deprecated, but still used by the HDF4 EOS server code. 00091 void 00092 parse_error(parser_arg * arg, const char *msg, const int line_num, 00093 const char *context) 00094 { 00095 // Jose Garcia 00096 // This assert(s) is (are) only for developing purposes 00097 // For production servers remove it by compiling with NDEBUG 00098 assert(arg); 00099 assert(msg); 00100 00101 arg->set_status(FALSE); 00102 00103 string oss = ""; 00104 00105 if (line_num != 0) { 00106 oss += "Error parsing the text on line "; 00107 append_long_to_string(line_num, 10, oss); 00108 } 00109 else { 00110 oss += "Parse error."; 00111 } 00112 00113 if (context) 00114 oss += (string) " at or near: " + context + (string) "\n" + msg 00115 + (string) "\n"; 00116 else 00117 oss += (string) "\n" + msg + (string) "\n"; 00118 00119 arg->set_error(new Error(unknown_error, oss)); 00120 } 00121 00122 void 00123 parse_error(const char *msg, const int line_num, const char *context) 00124 { 00125 // Jose Garcia 00126 // This assert(s) is (are) only for developing purposes 00127 // For production servers remove it by compiling with NDEBUG 00128 assert(msg); 00129 00130 string oss = ""; 00131 00132 if (line_num != 0) { 00133 oss += "Error parsing the text on line "; 00134 append_long_to_string(line_num, 10, oss); 00135 } 00136 else { 00137 oss += "Parse error."; 00138 } 00139 00140 if (context) 00141 oss += (string) " at or near: " + context + (string) "\n" + msg 00142 + (string) "\n"; 00143 else 00144 oss += (string) "\n" + msg + (string) "\n"; 00145 00146 throw Error(oss); 00147 } 00148 00149 // context comes from the parser and will always be a char * unless the 00150 // parsers change dramatically. 00151 void 00152 parse_error(const string & msg, const int line_num, const char *context) 00153 { 00154 parse_error(msg.c_str(), line_num, context); 00155 } 00156 00157 void save_str(char *dst, const char *src, const int line_num) 00158 { 00159 if (strlen(src) >= ID_MAX) 00160 parse_error(string("The word `") + string(src) 00161 + string("' is too long (it should be no longer than ") 00162 + long_to_string(ID_MAX) + string(")."), line_num); 00163 00164 strncpy(dst, src, ID_MAX); 00165 dst[ID_MAX - 1] = '\0'; /* in case ... */ 00166 } 00167 00168 void save_str(string & dst, const char *src, const int) 00169 { 00170 dst = src; 00171 } 00172 00173 bool is_keyword(string id, const string & keyword) 00174 { 00175 downcase(id); 00176 id = prune_spaces(id); 00177 DBG(cerr << "is_keyword: " << keyword << " = " << id << endl); 00178 return id == keyword; 00179 } 00180 00181 int check_byte(const char *val) 00182 { 00183 char *ptr; 00184 long v = strtol(val, &ptr, 0); 00185 00186 if ((v == 0 && val == ptr) || *ptr != '\0') { 00187 return FALSE; 00188 } 00189 00190 DBG(cerr << "v: " << v << endl); 00191 00192 // We're very liberal here with values. Anything that can fit into 8 bits 00193 // is allowed through. Clients will have to deal with the fact that the 00194 // ASCII representation for the value might need to be tweaked. This is 00195 // especially the case for Java clients where Byte datatypes are 00196 // signed. 3/20/2000 jhrg 00197 if ((v < 0 && v < DODS_SCHAR_MIN) 00198 || v > 0 && static_cast < unsigned long >(v) > DODS_UCHAR_MAX) 00199 return FALSE; 00200 00201 return TRUE; 00202 } 00203 00204 // This version of check_int will pass base 8, 10 and 16 numbers when they 00205 // use the ANSI standard for string representation of those number bases. 00206 00207 int check_int16(const char *val) 00208 { 00209 char *ptr; 00210 long v = strtol(val, &ptr, 0); // `0' --> use val to determine base 00211 00212 if ((v == 0 && val == ptr) || *ptr != '\0') { 00213 return FALSE; 00214 } 00215 // Don't use the constant from limits.h, use the ones in dods-limits.h 00216 if (v > DODS_SHRT_MAX || v < DODS_SHRT_MIN) { 00217 return FALSE; 00218 } 00219 00220 return TRUE; 00221 } 00222 00223 int check_uint16(const char *val) 00224 { 00225 char *ptr; 00226 unsigned long v = strtol(val, &ptr, 0); 00227 00228 if ((v == 0 && val == ptr) || *ptr != '\0') { 00229 return FALSE; 00230 } 00231 00232 if (v > DODS_USHRT_MAX) { 00233 return FALSE; 00234 } 00235 00236 return TRUE; 00237 } 00238 00239 int check_int32(const char *val) 00240 { 00241 char *ptr; 00242 long v = strtol(val, &ptr, 0); // `0' --> use val to determine base 00243 00244 if ((v == 0 && val == ptr) || *ptr != '\0') { 00245 return FALSE; 00246 } 00247 00248 if (v > DODS_INT_MAX || v < DODS_INT_MIN) { 00249 return FALSE; 00250 } 00251 00252 return TRUE; 00253 } 00254 00255 int check_uint32(const char *val) 00256 { 00257 char *ptr; 00258 unsigned long v = strtol(val, &ptr, 0); 00259 00260 if ((v == 0 && val == ptr) || *ptr != '\0') { 00261 return FALSE; 00262 } 00263 00264 return TRUE; 00265 } 00266 00267 // Check first for system errors (like numbers so small they convert 00268 // (erroneously) to zero. Then make sure that the value is within 00269 // limits. 00270 00271 int check_float32(const char *val) 00272 { 00273 char *ptr; 00274 errno = 0; // Clear previous value. Fix for the 64bit 00275 // IRIX from Rob Morris. 5/21/2001 jhrg 00276 00277 #ifdef WIN32 00278 double v = w32strtod(val, &ptr); 00279 #else 00280 double v = strtod(val, &ptr); 00281 #endif 00282 00283 DBG(cerr << "v: " << v << ", ptr: " << ptr 00284 << ", errno: " << errno << ", val==ptr: " << (val == ptr) << endl); 00285 if ((v == 0.0 && (val == ptr || errno == HUGE_VAL || errno == ERANGE)) 00286 || *ptr != '\0') { 00287 return FALSE; 00288 } 00289 00290 DBG(cerr << "fabs(" << val << ") = " << fabs(v) << endl); 00291 double abs_val = fabs(v); 00292 if (abs_val > DODS_FLT_MAX 00293 || (abs_val != 0.0 && abs_val < DODS_FLT_MIN)) 00294 return FALSE; 00295 00296 return TRUE; 00297 } 00298 00299 int check_float64(const char *val) 00300 { 00301 DBG(cerr << "val: " << val << endl); 00302 char *ptr; 00303 errno = 0; // Clear previous value. 5/21/2001 jhrg 00304 00305 #ifdef WIN32 00306 double v = w32strtod(val, &ptr); 00307 #else 00308 double v = strtod(val, &ptr); 00309 #endif 00310 00311 DBG(cerr << "v: " << v << ", ptr: " << ptr 00312 << ", errno: " << errno << ", val==ptr: " << (val == ptr) << endl); 00313 00314 if ((v == 0.0 && (val == ptr || errno == HUGE_VAL || errno == ERANGE)) 00315 || *ptr != '\0') { 00316 return FALSE; 00317 } 00318 00319 DBG(cerr << "fabs(" << val << ") = " << fabs(v) << endl); 00320 double abs_val = fabs(v); 00321 if (abs_val > DODS_DBL_MAX 00322 || (abs_val != 0.0 && abs_val < DODS_DBL_MIN)) 00323 return FALSE; 00324 00325 return TRUE; 00326 } 00327 00328 /* 00329 Maybe someday we will really check the Urls to see if they are valid... 00330 */ 00331 00332 int check_url(const char *) 00333 { 00334 return TRUE; 00335 } 00336 00337 } // namespace libdap