/*
* tokenutils.cc
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEST. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "tokenutils.h"
#include "integerdatum.h"
#include "doubledatum.h"
#include "namedatum.h"
#include "booldatum.h"
#include <string>
#include "stringdatum.h"
#include "symboldatum.h"
#include "arraydatum.h"
#include <cmath> // for sqrt()
#include "sliexceptions.h"
template<>
long getValue<long>(const Token&t)
{
const IntegerDatum *id= dynamic_cast<const IntegerDatum *>(t.datum());
if (id == NULL)
{// we have to create a Datum object to get the name...
IntegerDatum const d;
throw TypeMismatch(d.gettypename().toString(),
t.datum()->gettypename().toString());
}
return id->get();
}
template<>
void setValue<long>(const Token&t, long const &value)
{
IntegerDatum *id= dynamic_cast<IntegerDatum *>(t.datum());
if (id == NULL)
{// we have to create a Datum object to get the name...
IntegerDatum const d;
throw TypeMismatch(d.gettypename().toString(),
t.datum()->gettypename().toString());
}
(*id) = value;
}
template<>
Token newToken<long>(long const &value)
{
return Token( new IntegerDatum(value));
}
template<>
double getValue<double>(const Token&t)
{
DoubleDatum *id= dynamic_cast<DoubleDatum *>(t.datum());
if (id == NULL)
{// we have to create a Datum object to get the name...
DoubleDatum const d;
throw TypeMismatch(d.gettypename().toString(),
t.datum()->gettypename().toString());
}
return id->get();
}
template<>
void setValue<double>(const Token&t, double const &value)
{
DoubleDatum *id= dynamic_cast<DoubleDatum *>(t.datum());
if (id == NULL)
{// we have to create a Datum object to get the name...
DoubleDatum const d;
throw TypeMismatch(d.gettypename().toString(),
t.datum()->gettypename().toString());
}
(*id) = value;
}
template<>
float getValue<float>(const Token&t)
{
DoubleDatum *id= dynamic_cast<DoubleDatum *>(t.datum());
if (id == NULL)
{// we have to create a Datum object to get the name...
DoubleDatum const d;
throw TypeMismatch(d.gettypename().toString(),
t.datum()->gettypename().toString());
}
return (float)id->get();
}
template<>
void setValue<float>(const Token&t, float const &value)
{
DoubleDatum *id= dynamic_cast<DoubleDatum *>(t.datum());
if (id == NULL)
{// we have to create a Datum object to get the name...
DoubleDatum const d;
throw TypeMismatch(d.gettypename().toString(),
t.datum()->gettypename().toString());
}
(*id) = (double)value;
}
template<>
Token newToken<double>(double const &value)
{
return Token(new DoubleDatum(value));
}
template<>
bool getValue<bool>(const Token&t)
{
BoolDatum *bd = dynamic_cast<BoolDatum*>(t.datum());
if (bd == NULL)
{// we have to create a Datum object to get the name...
BoolDatum const d(false);
throw TypeMismatch(d.gettypename().toString(),
t.datum()->gettypename().toString());
}
return static_cast<bool>(*bd);
// we should have used i->true_name, bit we don't know the interpreter here.
}
template<>
void setValue<bool>(const Token&t, bool const &value)
{
BoolDatum *bd= dynamic_cast<BoolDatum *>(t.datum());
if (bd == NULL)
{// we have to create a Datum object to get the name...
BoolDatum const d(false);
throw TypeMismatch(d.gettypename().toString(),
t.datum()->gettypename().toString());
}
*bd = BoolDatum( value );
// we should have used i->true_name, bit we don't know the interpreter here.
}
template<>
Token newToken<bool>(bool const &value)
{
return Token(new BoolDatum( value));
// we should have used i->true_name, bit we don't know the interpreter here.
}
// These will handle StringDatum, NameDatum,
// LiteralDatum and SymbolDatum tokens:
template<>
std::string getValue<std::string>(const Token &t)
{
// If it is a StringDatum, it can be casted to a string:
std::string *s = dynamic_cast<std::string*>(t.datum());
if (s != NULL)
{
return *s;
}
else
{
// If it is a NameDatum, LiteralDatum or SymbolDatum,
// (or even a BoolDatum!) it can be casted to a Name:
Name *n = dynamic_cast<Name*>(t.datum());
if (n != NULL)
{
return n->toString();
}
else
{
// The given token can never yield a string!
// we have to create Datum objects to get the expected names...
StringDatum const d1;
NameDatum const d2("dummy");
LiteralDatum const d3("dummy");
SymbolDatum const d4("dummy");
throw TypeMismatch(d1.gettypename().toString() + ", " +
d2.gettypename().toString() + ", " +
d3.gettypename().toString() + ", or " +
d4.gettypename().toString(),
t.datum()->gettypename().toString());
}
}
}
template<>
void setValue<std::string>(const Token &t, std::string const &value)
{
// If it is a StringDatum, it can be casted to a string:
std::string *s = dynamic_cast<std::string*>(t.datum());
if (s != NULL)
{
*s = value;
}
else
{
// If it is a BoolDatum, it -could- be set from a string, but
// this operation shall not be allowed!
BoolDatum *b = dynamic_cast<BoolDatum*>(t.datum());
if (b != NULL)
{
// we have to create Datum objects to get the expected names...
StringDatum const d1;
NameDatum const d2("dummy");
LiteralDatum const d3("dummy");
SymbolDatum const d4("dummy");
throw TypeMismatch(d1.gettypename().toString() + ", " +
d2.gettypename().toString() + ", " +
d3.gettypename().toString() + ", or " +
d4.gettypename().toString(),
t.datum()->gettypename().toString());
}
else
{
// If it is a NameDatum, LiteralDatum or SymbolDatum,
// it can be casted to a Name:
Name *n = dynamic_cast<Name*>(t.datum());
if (n != NULL)
{
*n = Name(value);
}
else
{
// The given token can never hold a string!
// we have to create Datum objects to get the expected names...
StringDatum const d1;
NameDatum const d2("dummy");
LiteralDatum const d3("dummy");
SymbolDatum const d4("dummy");
throw TypeMismatch(d1.gettypename().toString() + ", " +
d2.gettypename().toString() + ", " +
d3.gettypename().toString() + ", or " +
d4.gettypename().toString(),
t.datum()->gettypename().toString());
}
}
}
}
// This will always yield StringDatum tokens:
#ifndef HAVE_SPECIALIZATION_BUG
template<>
Token newToken<std::string>(std::string const &value)
{
return Token( new StringDatum(value));
}
#endif
// These will convert homogeneous double arrays to vectors:
template<>
std::vector<double> getValue<std::vector<double> >(const Token &t)
{
// try DoubleVectorDatum first
DoubleVectorDatum* dvd = dynamic_cast<DoubleVectorDatum*>(t.datum());
if ( dvd )
return **dvd;
// ok, try ArrayDatum
ArrayDatum *ad= dynamic_cast<ArrayDatum *>(t.datum());
if ( ad )
{
std::vector<double> data;
ad->toVector(data);
return data;
}
// out of options
throw TypeMismatch(DoubleVectorDatum().gettypename().toString()
+ " or " + ArrayDatum().gettypename().toString(),
t.datum()->gettypename().toString());
}
template<>
void setValue<std::vector<double> >(const Token&t, std::vector<double> const &value)
{
ArrayDatum *ad= dynamic_cast<ArrayDatum *>(t.datum());
if (ad == NULL)
{// we have to create a Datum object to get the name...
ArrayDatum const d;
throw TypeMismatch(d.gettypename().toString(),
t.datum()->gettypename().toString());
}
// ArrayDatum is an AggregateDatum, which means, it is derived from
// TokenArray. Hence, we can use ad just like a TokenArray:
if (ad->size() != value.size())
{// arrays have incompatible size
throw RangeCheck(value.size());
}
for (size_t i=0; i<ad->size(); ++i)
{
setValue<double>((*ad)[i], value[i]);
}
}
#ifndef HAVE_SPECIALIZATION_BUG
template<>
Token newToken<std::vector<double> >(std::vector<double> const &value)
{
return Token( new ArrayDatum(value));
}
#endif
// These will convert homogeneous int arrays to vectors:
template<>
std::vector<long> getValue<std::vector<long> >(const Token &t)
{
// try IntVectorDatum first
IntVectorDatum* ivd = dynamic_cast<IntVectorDatum*>(t.datum());
if ( ivd )
return **ivd;
// ok, try ArrayDatum
ArrayDatum *ad= dynamic_cast<ArrayDatum *>(t.datum());
if ( ad )
{
std::vector<long> data;
ad->toVector(data);
return data;
}
// out of options
throw TypeMismatch(IntVectorDatum().gettypename().toString()
+ " or " + ArrayDatum().gettypename().toString(),
t.datum()->gettypename().toString());
}
template<>
void setValue<std::vector<long> >(const Token&t, std::vector<long> const &value)
{
ArrayDatum *ad= dynamic_cast<ArrayDatum *>(t.datum());
if (ad == NULL)
{// we have to create a Datum object to get the name...
ArrayDatum const d;
throw TypeMismatch(d.gettypename().toString(),
t.datum()->gettypename().toString());
}
// ArrayDatum is an AggregateDatum, which means, it is derived from
// TokenArray. Hence, we can use ad just like a TokenArray:
if (ad->size() != value.size())
{// arrays have incompatible size
throw RangeCheck(value.size());
}
for (size_t i=0; i<ad->size(); ++i)
{
setValue<long>((*ad)[i], value[i]);
}
}
template<>
Token newToken<std::vector<long> >(std::vector<long> const &value)
{
return Token( new ArrayDatum(value));
}
// These will convert homogeneous double arrays to valarrays:
template<>
std::valarray<double> getValue<std::valarray<double> >(const Token &t)
{
// first get data to vector, then copy to valarray
const std::vector<double> tmp = getValue<std::vector<double> >(t);
std::valarray<double> data(tmp.size());
for (size_t i = 0; i < tmp.size(); ++i )
data[i] = tmp[i];
return data;
}
template<>
void setValue<std::valarray<double> >(const Token&t, std::valarray<double> const &value)
{
ArrayDatum *ad= dynamic_cast<ArrayDatum *>(t.datum());
if (ad == NULL)
{// we have to create a Datum object to get the name...
ArrayDatum const d;
throw TypeMismatch(d.gettypename().toString(),
t.datum()->gettypename().toString());
}
// ArrayDatum is an AggregateDatum, which means, it is derived from
// TokenArray. Hence, we can use ad just like a TokenArray:
if (ad->size() != value.size())
{// arrays have incompatible size
throw RangeCheck(value.size());
}
for (size_t i=0; i<ad->size(); ++i)
{
setValue<double>((*ad)[i], value[i]);
}
}
#ifndef HAVE_SPECIALIZATION_BUG
template<>
Token newToken<std::valarray<double> >(std::valarray<double> const &value)
{
return Token( new ArrayDatum(value));
}
#endif
// These will convert homogeneous int arrays to valarrays:
template<>
std::valarray<long> getValue<std::valarray<long> >(const Token &t)
{
// first get data to vector, then copy to valarray
const std::vector<long> tmp = getValue<std::vector<long> >(t);
std::valarray<long> data(tmp.size());
for (size_t i = 0; i < tmp.size(); ++i )
data[i] = tmp[i];
return data;
}
template<>
void setValue<std::valarray<long> >(const Token&t, std::valarray<long> const &value)
{
ArrayDatum *ad= dynamic_cast<ArrayDatum *>(t.datum());
if (ad == NULL)
{// we have to create a Datum object to get the name...
ArrayDatum const d;
throw TypeMismatch(d.gettypename().toString(),
t.datum()->gettypename().toString());
}
// ArrayDatum is an AggregateDatum, which means, it is derived from
// TokenArray. Hence, we can use ad just like a TokenArray:
if (ad->size() != value.size())
{// arrays have incompatible size
throw RangeCheck(value.size());
}
for (size_t i=0; i<ad->size(); ++i)
{
setValue<long>((*ad)[i], value[i]);
}
}
template<>
Token newToken<std::valarray<long> >(std::valarray<long> const &value)
{
return Token( new ArrayDatum(value));
}