libdap  Updated for version 3.17.0
Error.cc
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00023 //
00024 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00025 
00026 // (c) COPYRIGHT URI/MIT 1994-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 // Implementation for the Error class.
00033 
00034 
00035 #include "config.h"
00036 
00037 #include <cstdio>
00038 #include <cassert>
00039 
00040 #include "Error.h"
00041 #include "parser.h"
00042 #include "InternalErr.h"
00043 #include "debug.h"
00044 
00045 using namespace std;
00046 
00047 // Glue routines declared in Error.lex
00048 extern void Error_switch_to_buffer(void *new_buffer);
00049 extern void Error_delete_buffer(void * buffer);
00050 extern void *Error_buffer(FILE *fp);
00051 
00052 //extern void Errorrestart(FILE *yyin); // defined in Error.tab.c
00053 extern int Errorparse(libdap::parser_arg *arg);
00054 
00055 namespace libdap {
00056 
00057 // There are two entries for 'cannot read file' because of an error made 
00058 // when the message was first added to this class. 
00059 static const char *err_messages[] = {
00060     "Undefined error",
00061     "Unknown error",
00062     "Internal error",
00063     "No such file",
00064     "No such variable",
00065     "Malformed expression",
00066     "No authorization",
00067     "Cannot read file",
00068     "Not Implemented",
00069     ""
00070 };
00071 
00074 Error::Error() : _error_code(undefined_error), _error_message("")
00075 {}
00076 
00086 Error::Error(ErrorCode ec, string msg)
00087         : _error_code(ec), _error_message(msg)
00088 {}
00089 
00095 Error::Error(string msg)
00096         : _error_code(unknown_error), _error_message(msg)
00097 {}
00098 
00099 Error::Error(const Error &copy_from)
00100         : _error_code(copy_from._error_code),
00101         _error_message(copy_from._error_message)
00102 {
00103 }
00104 
00105 Error::~Error()
00106 {
00107 }
00108 
00109 Error &
00110 Error::operator=(const Error &rhs)
00111 {
00112     assert(OK());
00113 
00114     if (&rhs == this)  // are they identical?
00115         return *this;
00116     else {
00117         _error_code = rhs._error_code;
00118         _error_message = rhs._error_message;
00119 
00120         assert(this->OK());
00121 
00122         return *this;
00123     }
00124 }
00125 
00132 bool
00133 Error::OK() const
00134 {
00135     // The object is empty - users cannot make these, but this class can!
00136     bool empty = ((_error_code == undefined_error)
00137                   && (_error_message.empty()));
00138 
00139     // Just a message - the program part is null.
00140     bool message = ((_error_code != undefined_error)
00141                     && (!_error_message.empty()));
00142 
00143     DBG(cerr << "empty: " << empty << ", message: " << message << endl);
00144     return empty || message;
00145 }
00146 
00155 bool
00156 Error::parse(FILE *fp)
00157 {
00158     if (!fp)
00159         throw InternalErr(__FILE__, __LINE__, "Null input stream");
00160 
00161     void *buffer = Error_buffer(fp);
00162     Error_switch_to_buffer(buffer);
00163 
00164     parser_arg arg(this);
00165 
00166     bool status;
00167     try {
00168         status = Errorparse(&arg) == 0;
00169         Error_delete_buffer(buffer);
00170     }
00171     catch (Error &e) {
00172         Error_delete_buffer(buffer);
00173         throw InternalErr(__FILE__, __LINE__, e.get_error_message());
00174     }
00175 
00176     // STATUS is the result of the parser function; if a recoverable error
00177     // was found it will be true but arg.status() will be false.
00178     // I'm throwing an InternalErr here since Error objects are generated by
00179     // the core; they should always parse! 9/21/2000 jhrg
00180     if (!status || !arg.status())
00181         throw InternalErr(__FILE__, __LINE__, "Error parsing error object!");
00182     else
00183         return OK();  // Check object consistency
00184 }
00185 
00186 
00197 void
00198 Error::print(FILE *out) const
00199 {
00200     assert(OK());
00201 
00202     fprintf(out, "Error {\n") ;
00203 
00204     fprintf(out, "    code = %d;\n", static_cast<int>(_error_code)) ;
00205 
00206     // If the error message is wrapped in double quotes, print it, else, add
00207     // wrapping double quotes.
00208     if (*_error_message.begin() == '"' && *(_error_message.end() - 1) == '"')
00209         fprintf(out, "    message = %s;\n", _error_message.c_str()) ;
00210     else
00211         fprintf(out, "    message = \"%s\";\n", _error_message.c_str()) ;
00212 
00213     fprintf(out, "};\n") ;
00214 }
00215 
00226 void
00227 Error::print(ostream &strm) const
00228 {
00229     assert(OK());
00230 
00231     strm << "Error {\n" ;
00232 
00233     strm << "    code = " << static_cast<int>(_error_code) << ";\n" ;
00234 
00235     // If the error message is wrapped in double quotes, print it, else, add
00236     // wrapping double quotes.
00237     if (*_error_message.begin() == '"' && *(_error_message.end() - 1) == '"')
00238         strm << "    message = " << _error_message.c_str() << ";\n" ;
00239     else
00240         strm << "    message = \"" << _error_message.c_str() << "\";\n"  ;
00241 
00242     strm << "};\n" ;
00243 }
00244 
00246 ErrorCode
00247 Error::get_error_code() const
00248 {
00249     assert(OK());
00250     return _error_code;
00251 }
00252 
00259 void
00260 Error::set_error_code(ErrorCode ec)
00261 {
00262     _error_code = ec;
00263     // Added check to make sure that err_messages is not accessed beyond its
00264     // bounds. 02/02/04 jhrg
00265     if (_error_message.empty()
00266         && ec > undefined_error && ec <= cannot_read_file) {
00267         _error_message = err_messages[ec - undefined_error];
00268     }
00269     else {
00270         _error_message = err_messages[0];
00271     }
00272 }
00273 
00275 string
00276 Error::get_error_message() const
00277 {
00278     assert(OK());
00279 
00280     return string(_error_message);
00281 }
00282 
00284 void
00285 Error::set_error_message(string msg)
00286 {
00287     _error_message = msg;
00288 }
00289 
00290 } // namespace libdap