libcruft-util/json/constraint/inequality.cpp

91 lines
3.2 KiB
C++

/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
*/
#include "inequality.hpp"
#include "../tree.hpp"
using util::json::schema::constraint::inequality;
///////////////////////////////////////////////////////////////////////////////
template <template <typename> class ComparatorT>
inequality<ComparatorT>::inequality (::json::tree::node const &def)
{
if (!def.is_number ())
throw constraint_error<inequality> (def);
auto const &val = def.as_number ();
switch (val.repr ()) {
case ::json::tree::number::UINT: m_value = val.uint (); break;
case ::json::tree::number::SINT: m_value = val.sint (); break;
case ::json::tree::number::REAL: m_value = val.real (); break;
}
}
///////////////////////////////////////////////////////////////////////////////
template <template <typename> class ComparatorT>
typename inequality<ComparatorT>::output_iterator
inequality<ComparatorT>::validate (util::json::schema::constraint::base::output_iterator res,
::json::tree::node &target) const noexcept
{
if (!target.is_number ()) {
return *res++ = failure { .rule = *this, .target = target };
}
// HACK: this shouldn't be casting to double for the comparison, but it
// greatly simplifies the logic.
auto const &value = target.as_number ();
std::visit([&,this] (auto const &inner) noexcept {
if (!ComparatorT<double>{} (value.as<double> (), inner))
*res++ = failure { .rule = *this, .target = target };
}, m_value);
return res;
}
///////////////////////////////////////////////////////////////////////////////
template <template <typename> class ComparatorT>
std::ostream&
inequality<ComparatorT>::describe (std::ostream &os) const
{
os << "{ " << util::type_name_v<inequality> << ": ";
std::visit ([&os] (auto const &i) -> void { os << i; }, m_value);
return os << " }";
}
///////////////////////////////////////////////////////////////////////////////
template class util::json::schema::constraint::inequality<std::less_equal>;
template class util::json::schema::constraint::inequality<std::greater_equal>;
template class util::json::schema::constraint::inequality<std::less>;
template class util::json::schema::constraint::inequality<std::greater>;
///////////////////////////////////////////////////////////////////////////////
template <>
bool
util::json::schema::constraint::is_multiple<double>::operator() (double a, double b) const noexcept
{
return std::fmod (a, b) <= 1e-8;
}
//-----------------------------------------------------------------------------
template class util::json::schema::constraint::inequality<util::json::schema::constraint::is_multiple>;