2015-08-30 04:57:32 +02:00
|
|
|
/*
|
|
|
|
|
GenNode - generic node element for tree like data representation
|
|
|
|
|
|
|
|
|
|
Copyright (C) Lumiera.org
|
|
|
|
|
2015, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
|
|
|
|
|
|
This program 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.
|
|
|
|
|
|
|
|
|
|
This program 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 this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
|
|
|
|
* *****************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @file gen-node.cpp
|
|
|
|
|
** Generic node element (implementation parts).
|
|
|
|
|
** Some of the more technical details regarding value access and
|
|
|
|
|
** comparisons has been moved down within this compilation unit,
|
|
|
|
|
** to cut down compilation time.
|
|
|
|
|
**
|
|
|
|
|
** \par comparison and match
|
|
|
|
|
**
|
|
|
|
|
** The DataCap element provides a set of functions to check for \em equivalence
|
|
|
|
|
** or match. These are used to build a recursive containment check. To implement
|
|
|
|
|
** such predicates, we need to build a one-way off visitor for use with lib::Variant.
|
|
|
|
|
** These specifically tailored functors only define \c handle(TY) functions for the
|
|
|
|
|
** cases actually of interest. All other cases invoke the default handling, which
|
|
|
|
|
** returns \c false.
|
|
|
|
|
**
|
|
|
|
|
** @see gen-node-basic-test.cpp
|
|
|
|
|
**
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "lib/error.hpp"
|
|
|
|
|
#include "lib/format-util.hpp"
|
|
|
|
|
#include "lib/diff/diff-language.hpp"
|
|
|
|
|
#include "lib/diff/gen-node.hpp"
|
|
|
|
|
#include "lib/util-quant.hpp"
|
|
|
|
|
#include "lib/variant.hpp"
|
|
|
|
|
|
|
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using boost::lexical_cast;
|
|
|
|
|
using lib::time::TimeValue;
|
|
|
|
|
using util::almostEqual;
|
|
|
|
|
using lib::hash::LuidH;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace lib {
|
|
|
|
|
namespace diff{
|
|
|
|
|
|
|
|
|
|
/* symbolic marker ID references
|
|
|
|
|
* used within the tree diff language
|
|
|
|
|
* to mark specific scopes
|
|
|
|
|
*/
|
2015-10-09 03:03:27 +02:00
|
|
|
const Ref Ref::END ("_END_");
|
|
|
|
|
const Ref Ref::THIS ("_THIS_");
|
|
|
|
|
const Ref Ref::CHILD ("_CHILD_");
|
|
|
|
|
const Ref Ref::ATTRIBS("_ATTRIBS_");
|
2015-08-30 04:57:32 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Implementation of content equality test
|
|
|
|
|
* @throws error::Logic when the given other DataCap
|
|
|
|
|
* does not hold a value of the same type than
|
|
|
|
|
* this DataCap.
|
|
|
|
|
* @remarks since the GenNode::ID is generated including a type hash,
|
|
|
|
|
* the equality operator of GenNode ensures this content test
|
|
|
|
|
* is only called on a compatible DataCap.
|
|
|
|
|
*/
|
|
|
|
|
bool
|
|
|
|
|
DataCap::matchData (DataCap const& o) const
|
|
|
|
|
{
|
|
|
|
|
class EqualityTest
|
|
|
|
|
: public Variant<DataValues>::Predicate
|
|
|
|
|
{
|
|
|
|
|
DataCap const& o_;
|
|
|
|
|
|
|
|
|
|
#define DERIVE_EQUALITY(_TY_) \
|
|
|
|
|
virtual bool handle (_TY_ const& val) override { return (o_.get<_TY_>() == val); }
|
|
|
|
|
|
|
|
|
|
DERIVE_EQUALITY (int)
|
|
|
|
|
DERIVE_EQUALITY (int64_t)
|
|
|
|
|
DERIVE_EQUALITY (short)
|
|
|
|
|
DERIVE_EQUALITY (char)
|
|
|
|
|
DERIVE_EQUALITY (bool)
|
|
|
|
|
DERIVE_EQUALITY (double)
|
|
|
|
|
DERIVE_EQUALITY (string)
|
|
|
|
|
DERIVE_EQUALITY (time::Time)
|
|
|
|
|
DERIVE_EQUALITY (time::Offset)
|
|
|
|
|
DERIVE_EQUALITY (time::Duration)
|
|
|
|
|
DERIVE_EQUALITY (time::TimeSpan)
|
|
|
|
|
DERIVE_EQUALITY (hash::LuidH)
|
|
|
|
|
DERIVE_EQUALITY (RecRef)
|
|
|
|
|
DERIVE_EQUALITY (Rec)
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
EqualityTest(DataCap const& o)
|
|
|
|
|
: o_(o)
|
|
|
|
|
{ }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
EqualityTest visitor(o);
|
|
|
|
|
return accept(visitor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
DataCap::matchNum (int64_t num) const
|
|
|
|
|
{
|
|
|
|
|
class MatchNumber
|
|
|
|
|
: public Variant<DataValues>::Predicate
|
|
|
|
|
{
|
|
|
|
|
int64_t num_;
|
|
|
|
|
|
|
|
|
|
#define MATCH_NUMBER(_TY_) \
|
|
|
|
|
virtual bool handle (_TY_ const& val) override { return val == num_; }
|
|
|
|
|
|
|
|
|
|
MATCH_NUMBER (int)
|
|
|
|
|
MATCH_NUMBER (int64_t)
|
|
|
|
|
MATCH_NUMBER (short)
|
|
|
|
|
MATCH_NUMBER (char)
|
|
|
|
|
MATCH_NUMBER (double)
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
MatchNumber(int64_t num)
|
|
|
|
|
: num_(num)
|
|
|
|
|
{ }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
MatchNumber visitor(num);
|
|
|
|
|
return accept(visitor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
DataCap::matchDbl (double d) const
|
|
|
|
|
{
|
|
|
|
|
class MatchDouble
|
|
|
|
|
: public Variant<DataValues>::Predicate
|
|
|
|
|
{
|
|
|
|
|
double num_;
|
|
|
|
|
|
|
|
|
|
#define MATCH_DOUBLE(_TY_) \
|
|
|
|
|
virtual bool handle (_TY_ const& val) override { return almostEqual (double(val), num_); }
|
|
|
|
|
|
|
|
|
|
MATCH_DOUBLE (int)
|
|
|
|
|
MATCH_DOUBLE (int64_t)
|
|
|
|
|
MATCH_DOUBLE (short)
|
|
|
|
|
MATCH_DOUBLE (char)
|
|
|
|
|
MATCH_DOUBLE (double)
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
MatchDouble(double d)
|
|
|
|
|
: num_(d)
|
|
|
|
|
{ }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
MatchDouble visitor(d);
|
|
|
|
|
return accept(visitor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
DataCap::matchTxt (string const& text) const
|
|
|
|
|
{
|
|
|
|
|
class MatchString
|
|
|
|
|
: public Variant<DataValues>::Predicate
|
|
|
|
|
{
|
|
|
|
|
string const& txt_;
|
|
|
|
|
|
|
|
|
|
#define MATCH_STRING(_TY_) \
|
|
|
|
|
virtual bool handle (_TY_ const& val) override { return lexical_cast<string>(val) == txt_; }
|
|
|
|
|
|
|
|
|
|
MATCH_STRING (int)
|
|
|
|
|
MATCH_STRING (int64_t)
|
|
|
|
|
MATCH_STRING (short)
|
|
|
|
|
MATCH_STRING (double)
|
|
|
|
|
MATCH_STRING (bool)
|
|
|
|
|
|
|
|
|
|
virtual bool handle (string const& str) override { return str == txt_; }
|
|
|
|
|
virtual bool handle (char const& c ) override { return 1 == txt_.length() && txt_.front() == c; }
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
MatchString(string const& text)
|
|
|
|
|
: txt_(text)
|
|
|
|
|
{ }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
MatchString visitor(text);
|
|
|
|
|
return accept(visitor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
DataCap::matchTime (TimeValue time) const
|
|
|
|
|
{
|
|
|
|
|
class MatchTime
|
|
|
|
|
: public Variant<DataValues>::Predicate
|
|
|
|
|
{
|
|
|
|
|
TimeValue& t_;
|
|
|
|
|
|
|
|
|
|
#define MATCH_TIME(_TY_) \
|
|
|
|
|
virtual bool handle (_TY_ const& val) override { return val == t_; }
|
|
|
|
|
|
|
|
|
|
MATCH_TIME (time::Time)
|
|
|
|
|
MATCH_TIME (time::Offset)
|
|
|
|
|
MATCH_TIME (time::Duration)
|
|
|
|
|
MATCH_TIME (time::TimeSpan)
|
|
|
|
|
MATCH_TIME (hash::LuidH)
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
MatchTime(TimeValue& t)
|
|
|
|
|
: t_(t)
|
|
|
|
|
{ }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
MatchTime visitor(time);
|
|
|
|
|
return accept(visitor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
DataCap::matchBool (bool b) const
|
|
|
|
|
{
|
|
|
|
|
bool* val = unConst(this)->maybeGet<bool>();
|
|
|
|
|
return val && (b == *val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
DataCap::matchLuid (LuidH hash) const
|
|
|
|
|
{
|
|
|
|
|
LuidH* val = unConst(this)->maybeGet<LuidH>();
|
|
|
|
|
return val && (hash == *val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
DataCap::matchRec (RecRef const& ref) const
|
|
|
|
|
{
|
|
|
|
|
if (ref)
|
|
|
|
|
return matchRec (*ref.get());
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
RecRef* val = unConst(this)->maybeGet<RecRef>();
|
|
|
|
|
return val && val->empty();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
DataCap::matchRec (Rec const& rec) const
|
|
|
|
|
{
|
|
|
|
|
Rec* val = unConst(this)->maybeGet<Rec>();
|
|
|
|
|
if (!val)
|
|
|
|
|
{
|
|
|
|
|
RecRef* r = unConst(this)->maybeGet<RecRef>();
|
|
|
|
|
if (r) val = r->get();
|
|
|
|
|
}
|
|
|
|
|
return val && (rec == *val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DataCap::operator string() const
|
|
|
|
|
{
|
|
|
|
|
return "DataCap|"+string(this->buffer());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}} // namespace lib::diff
|