Blame Byte.cc

Packit a4aae4
Packit a4aae4
// -*- mode: c++; c-basic-offset:4 -*-
Packit a4aae4
Packit a4aae4
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
Packit a4aae4
// Access Protocol.
Packit a4aae4
Packit a4aae4
// Copyright (c) 2002,2003 OPeNDAP, Inc.
Packit a4aae4
// Author: James Gallagher <jgallagher@opendap.org>
Packit a4aae4
//
Packit a4aae4
// This library is free software; you can redistribute it and/or
Packit a4aae4
// modify it under the terms of the GNU Lesser General Public
Packit a4aae4
// License as published by the Free Software Foundation; either
Packit a4aae4
// version 2.1 of the License, or (at your option) any later version.
Packit a4aae4
//
Packit a4aae4
// This library is distributed in the hope that it will be useful,
Packit a4aae4
// but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a4aae4
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit a4aae4
// Lesser General Public License for more details.
Packit a4aae4
//
Packit a4aae4
// You should have received a copy of the GNU Lesser General Public
Packit a4aae4
// License along with this library; if not, write to the Free Software
Packit a4aae4
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit a4aae4
//
Packit a4aae4
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
Packit a4aae4
Packit a4aae4
// (c) COPYRIGHT URI/MIT 1994-1999
Packit a4aae4
// Please read the full copyright statement in the file COPYRIGHT_URI.
Packit a4aae4
//
Packit a4aae4
// Authors:
Packit a4aae4
//      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
Packit a4aae4
Packit a4aae4
// Implementation for Byte.
Packit a4aae4
//
Packit a4aae4
// jhrg 9/7/94
Packit a4aae4
Packit a4aae4
//#define DODS_DEBUG
Packit a4aae4
Packit a4aae4
#include "config.h"
Packit a4aae4
Packit a4aae4
#include <sstream>
Packit a4aae4
Packit a4aae4
#include "Byte.h"           // synonymous with UInt8 and Char
Packit a4aae4
#include "Int8.h"
Packit a4aae4
#include "Int16.h"
Packit a4aae4
#include "UInt16.h"
Packit a4aae4
#include "Int32.h"
Packit a4aae4
#include "UInt32.h"
Packit a4aae4
#include "Int64.h"
Packit a4aae4
#include "UInt64.h"
Packit a4aae4
#include "Float32.h"
Packit a4aae4
#include "Float64.h"
Packit a4aae4
#include "Str.h"
Packit a4aae4
#include "Url.h"
Packit a4aae4
Packit a4aae4
#include "DDS.h"
Packit a4aae4
#include "Operators.h"
Packit a4aae4
#include "Marshaller.h"
Packit a4aae4
#include "UnMarshaller.h"
Packit a4aae4
Packit a4aae4
#include "DMR.h"
Packit a4aae4
#include "D4Attributes.h"
Packit a4aae4
#include "D4StreamMarshaller.h"
Packit a4aae4
#include "D4StreamUnMarshaller.h"
Packit a4aae4
Packit a4aae4
#include "debug.h"
Packit a4aae4
#include "util.h"
Packit a4aae4
#include "parser.h"
Packit a4aae4
#include "dods-limits.h"
Packit a4aae4
#include "InternalErr.h"
Packit a4aae4
Packit a4aae4
using std::cerr;
Packit a4aae4
using std::endl;
Packit a4aae4
Packit a4aae4
namespace libdap {
Packit a4aae4
Packit a4aae4
/** The Byte constructor requires only the name of the variable
Packit a4aae4
    to be created.  The name may be omitted, which will create a
Packit a4aae4
    nameless variable.  This may be adequate for some applications.
Packit a4aae4
Packit a4aae4
    @brief The Byte constructor.
Packit a4aae4
    @param n A string containing the name of the variable to be
Packit a4aae4
    created.
Packit a4aae4
Packit a4aae4
*/
Packit a4aae4
Byte::Byte(const string & n): BaseType(n, dods_byte_c), d_buf(0)
Packit a4aae4
{}
Packit a4aae4
Packit a4aae4
/** This Byte constructor requires the name of the variable to be created
Packit a4aae4
    and the name of the dataset from which this variable is being created.
Packit a4aae4
    This constructor is used in server-side processing, loading structure in
Packit a4aae4
    from a dataset.
Packit a4aae4
Packit a4aae4
    @brief The Byte server-side constructor.
Packit a4aae4
    @param n A string containing the name of the variable to be created.
Packit a4aae4
    @param d A string containing the name of the dataset from which the
Packit a4aae4
    variable is being created.
Packit a4aae4
*/
Packit a4aae4
Byte::Byte(const string &n, const string &d): BaseType(n, d, dods_byte_c), d_buf(0)
Packit a4aae4
{}
Packit a4aae4
Packit a4aae4
Byte::Byte(const Byte & copy_from): BaseType(copy_from)
Packit a4aae4
{
Packit a4aae4
    d_buf = copy_from.d_buf;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
BaseType *Byte::ptr_duplicate()
Packit a4aae4
{
Packit a4aae4
    return new Byte(*this);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
Byte & Byte::operator=(const Byte & rhs)
Packit a4aae4
{
Packit a4aae4
    if (this == &rhs)
Packit a4aae4
        return *this;
Packit a4aae4
Packit a4aae4
    dynamic_cast < BaseType & >(*this) = rhs;
Packit a4aae4
Packit a4aae4
    d_buf = rhs.d_buf;
Packit a4aae4
Packit a4aae4
    return *this;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
unsigned int Byte::width(bool) const
Packit a4aae4
{
Packit a4aae4
    return sizeof(dods_byte);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Serialize the contents of member _BUF (the object's internal
Packit a4aae4
    buffer, used to hold data) and write the result to stdout. If
Packit a4aae4
    FLUSH is true, write the contents of the output buffer to the
Packit a4aae4
    kernel. FLUSH is false by default. If CE_EVAL is true, evaluate
Packit a4aae4
    the current constraint expression; only send data if the CE
Packit a4aae4
    evaluates to true.
Packit a4aae4
Packit a4aae4
    @return False if a failure to read, send or flush is detected, true
Packit a4aae4
    otherwise.
Packit a4aae4
*/
Packit a4aae4
bool Byte::serialize(ConstraintEvaluator & eval, DDS & dds, Marshaller &m, bool ce_eval)
Packit a4aae4
{
Packit a4aae4
#if USE_LOCAL_TIMEOUT_SCHEME
Packit a4aae4
    dds.timeout_on();
Packit a4aae4
#endif
Packit a4aae4
    if (!read_p())
Packit a4aae4
        read();          // read() throws Error and InternalErr
Packit a4aae4
Packit a4aae4
    if (ce_eval && !eval.eval_selection(dds, dataset()))
Packit a4aae4
        return true;
Packit a4aae4
#if USE_LOCAL_TIMEOUT_SCHEME
Packit a4aae4
    dds.timeout_off();
Packit a4aae4
#endif
Packit a4aae4
    m.put_byte( d_buf ) ;
Packit a4aae4
Packit a4aae4
    return true;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief Deserialize the char on stdin and put the result in
Packit a4aae4
    <tt>_BUF</tt>.
Packit a4aae4
*/
Packit a4aae4
bool Byte::deserialize(UnMarshaller &um, DDS *, bool)
Packit a4aae4
{
Packit a4aae4
    um.get_byte( d_buf ) ;
Packit a4aae4
Packit a4aae4
    return false;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Byte::compute_checksum(Crc32 &checksum)
Packit a4aae4
{
Packit a4aae4
	checksum.AddData(reinterpret_cast<uint8_t*>(&d_buf), sizeof(d_buf));
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * @brief Serialize a Byte
Packit a4aae4
 * @param m
Packit a4aae4
 * @param dmr Unused
Packit a4aae4
 * @param eval Unused
Packit a4aae4
 * @param filter Unused
Packit a4aae4
 * @exception Error is thrown if the value needs to be read and that operation fails.
Packit a4aae4
 */
Packit a4aae4
void
Packit a4aae4
Byte::serialize(D4StreamMarshaller &m, DMR &, /*ConstraintEvaluator &,*/ bool)
Packit a4aae4
{
Packit a4aae4
    if (!read_p())
Packit a4aae4
        read();          // read() throws Error
Packit a4aae4
Packit a4aae4
    m.put_byte( d_buf ) ;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Byte::deserialize(D4StreamUnMarshaller &um, DMR &)
Packit a4aae4
{
Packit a4aae4
    um.get_byte( d_buf ) ;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Store the value referenced by val in the object's internal
Packit a4aae4
    buffer. reuse has no effect because this class does not
Packit a4aae4
    dynamically allocate storage for the internal buffer.
Packit a4aae4
Packit a4aae4
    @return The size (in bytes) of the value's representation.  */
Packit a4aae4
unsigned int Byte::val2buf(void *val, bool)
Packit a4aae4
{
Packit a4aae4
    // Jose Garcia
Packit a4aae4
    // This method is public therefore and I believe it has being designed
Packit a4aae4
    // to be use by read which must be implemented on the surrogate library,
Packit a4aae4
    // thus if the pointer val is NULL, is an Internal Error.
Packit a4aae4
    if (!val)
Packit a4aae4
        throw InternalErr("the incoming pointer does not contain any data.");
Packit a4aae4
Packit a4aae4
    d_buf = *(dods_byte *) val;
Packit a4aae4
Packit a4aae4
    return width();
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
unsigned int Byte::buf2val(void **val)
Packit a4aae4
{
Packit a4aae4
    // Jose Garcia
Packit a4aae4
    // The same comment justifying throwing an Error in val2buf applies here.
Packit a4aae4
    if (!val)
Packit a4aae4
        throw InternalErr("NULL pointer");
Packit a4aae4
Packit a4aae4
    if (!*val)
Packit a4aae4
        *val = new dods_byte;
Packit a4aae4
Packit a4aae4
    *(dods_byte *) * val = d_buf;
Packit a4aae4
Packit a4aae4
    return width();
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Set the value of this instance.
Packit a4aae4
    @param value The value
Packit a4aae4
    @return Always returns true; the return type of bool is for compatibility
Packit a4aae4
    with the Passive* subclasses written by HAO. */
Packit a4aae4
bool Byte::set_value(dods_byte value)
Packit a4aae4
{
Packit a4aae4
    d_buf = value;
Packit a4aae4
    set_read_p(true);
Packit a4aae4
Packit a4aae4
    return true;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Get the value of this instance.
Packit a4aae4
    @return The value. */
Packit a4aae4
dods_byte Byte::value() const
Packit a4aae4
{
Packit a4aae4
    return d_buf;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void Byte::print_val(FILE * out, string space, bool print_decl_p)
Packit a4aae4
{
Packit a4aae4
    ostringstream oss;
Packit a4aae4
    print_val(oss, space, print_decl_p);
Packit a4aae4
    fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void Byte::print_val(ostream &out, string space, bool print_decl_p)
Packit a4aae4
{
Packit a4aae4
    if (print_decl_p) {
Packit a4aae4
        print_decl(out, space, false);
Packit a4aae4
        out << " = " << (int) d_buf << ";\n";
Packit a4aae4
    }
Packit a4aae4
    else
Packit a4aae4
        out << (int) d_buf;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
bool Byte::ops(BaseType * b, int op)
Packit a4aae4
{
Packit a4aae4
Packit a4aae4
    // Extract the Byte arg's value.
Packit a4aae4
    if (!read_p() && !read()) {
Packit a4aae4
        // Jose Garcia
Packit a4aae4
        // Since the read method is virtual and implemented outside
Packit a4aae4
        // libdap++ if we cannot read the data that is the problem
Packit a4aae4
        // of the user or of whoever wrote the surrogate library
Packit a4aae4
        // implementing read therefore it is an internal error.
Packit a4aae4
        throw InternalErr("This value not read!");
Packit a4aae4
    }
Packit a4aae4
    // Extract the second arg's value.
Packit a4aae4
    if (!b || !(b->read_p() || b->read())) {
Packit a4aae4
        // Jose Garcia
Packit a4aae4
        // Since the read method is virtual and implemented outside
Packit a4aae4
        // libdap++ if we cannot read the data that is the problem
Packit a4aae4
        // of the user or of whoever wrote the surrogate library
Packit a4aae4
        // implementing read therefore it is an internal error.
Packit a4aae4
        throw InternalErr("This value not read!");
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    // By using the same operator code numbers for both the DAP2 and DAP4
Packit a4aae4
    // parser/evaluator we can use the same evaluation code.
Packit a4aae4
    return d4_ops(b, op);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * @see BaseType::d4_ops(BaseType *, int)
Packit a4aae4
 */
Packit a4aae4
bool Byte::d4_ops(BaseType *b, int op)
Packit a4aae4
{
Packit a4aae4
    switch (b->type()) {
Packit a4aae4
        case dods_int8_c:
Packit a4aae4
            return USCmp<dods_byte, dods_int8>(op, d_buf, static_cast<Int8*>(b)->value());
Packit a4aae4
        case dods_byte_c:
Packit a4aae4
            return Cmp<dods_byte, dods_byte>(op, d_buf, static_cast<Byte*>(b)->value());
Packit a4aae4
        case dods_int16_c:
Packit a4aae4
            return USCmp<dods_byte, dods_int16>(op, d_buf, static_cast<Int16*>(b)->value());
Packit a4aae4
        case dods_uint16_c:
Packit a4aae4
            return Cmp<dods_byte, dods_uint16>(op, d_buf, static_cast<UInt16*>(b)->value());
Packit a4aae4
        case dods_int32_c:
Packit a4aae4
            return USCmp<dods_byte, dods_int32>(op, d_buf, static_cast<Int32*>(b)->value());
Packit a4aae4
        case dods_uint32_c:
Packit a4aae4
            return Cmp<dods_byte, dods_uint32>(op, d_buf, static_cast<UInt32*>(b)->value());
Packit a4aae4
        case dods_int64_c:
Packit a4aae4
            return USCmp<dods_byte, dods_int64>(op, d_buf, static_cast<Int64*>(b)->value());
Packit a4aae4
        case dods_uint64_c:
Packit a4aae4
            return Cmp<dods_byte, dods_uint64>(op, d_buf, static_cast<UInt64*>(b)->value());
Packit a4aae4
        case dods_float32_c:
Packit a4aae4
            return USCmp<dods_byte, dods_float32>(op, d_buf, static_cast<Float32*>(b)->value());
Packit a4aae4
        case dods_float64_c:
Packit a4aae4
            return USCmp<dods_byte, dods_float64>(op, d_buf, static_cast<Float64*>(b)->value());
Packit a4aae4
        case dods_str_c:
Packit a4aae4
        case dods_url_c:
Packit a4aae4
            throw Error(malformed_expr, "Relational operators can only compare compatible types (number, string).");
Packit a4aae4
        default:
Packit a4aae4
            throw Error(malformed_expr, "Relational operators only work with scalar types.");
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
Packit a4aae4
Packit a4aae4
Packit a4aae4
/** @brief DAP4 to DAP2 transform
Packit a4aae4
 *
Packit a4aae4
 * Return a DAP2 'copy' of the variable.
Packit a4aae4
 *
Packit a4aae4
 * NOTE: This little bit of magic ensures that the DAP4 shenanigans
Packit a4aae4
 * in which UInt8, Char , and Byte are synonymous is reduced
Packit a4aae4
 * to the DAP2 simplicity of Byte.
Packit a4aae4
 *
Packit a4aae4
 *
Packit a4aae4
 * @param root The root group that should hold this new variable. Add Group-level
Packit a4aae4
 * stuff here (e.g., D4Dimensions).
Packit a4aae4
 * @param container Add the new variable to this container.
Packit a4aae4
 *
Packit a4aae4
 * @return A pointer to the transformed variable
Packit a4aae4
 */
Packit a4aae4
std::vector<BaseType *> *
Packit a4aae4
Byte::transform_to_dap2(AttrTable *parent_attr_table)
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << __func__ << "() - BEGIN" << endl;);
Packit a4aae4
    vector<BaseType *> *vec = BaseType::transform_to_dap2(parent_attr_table);
Packit a4aae4
    if(vec->size()!=1){
Packit a4aae4
        ostringstream oss;
Packit a4aae4
        oss << __func__ << "() -  Something Bad Happened. This transform should produce only ";
Packit a4aae4
        oss << " a single BaseType yet it produced " << vec->size();
Packit a4aae4
        throw new Error(internal_error,oss.str());
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    BaseType *dest = (*vec)[0];
Packit a4aae4
    DBG(cerr << __func__ << "() - type():       " << type() << endl;);
Packit a4aae4
    DBG(cerr << __func__ << "() - dest->type(): " << dest->type() << endl;);
Packit a4aae4
Packit a4aae4
    // This little bit of magic ensures that the DAP4 shenanigans
Packit a4aae4
    // in which UInt8, Char , and Byte are synonymous is reduced
Packit a4aae4
    // to the DAP2 simplicity of Byte.
Packit a4aae4
    if(type()!=dods_byte_c){
Packit a4aae4
        dest->set_type(dods_byte_c);
Packit a4aae4
    }
Packit a4aae4
    DBG (dest->get_attr_table().print(cerr););
Packit a4aae4
Packit a4aae4
    DBG(cerr << __func__ << "() - END" << endl;);
Packit a4aae4
    return vec;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief dumps information about this object
Packit a4aae4
 *
Packit a4aae4
 * Displays the pointer value of this instance and information about this
Packit a4aae4
 * instance.
Packit a4aae4
 *
Packit a4aae4
 * @param strm C++ i/o stream to dump the information to
Packit a4aae4
 * @return void
Packit a4aae4
 */
Packit a4aae4
void Byte::dump(ostream & strm) const
Packit a4aae4
{
Packit a4aae4
    strm << DapIndent::LMarg << "Byte::dump - ("
Packit a4aae4
    << (void *) this << ")" << endl;
Packit a4aae4
    DapIndent::Indent();
Packit a4aae4
    BaseType::dump(strm);
Packit a4aae4
    strm << DapIndent::LMarg << "value: " << d_buf << endl;
Packit a4aae4
    DapIndent::UnIndent();
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
} // namespace libdap