/** * @file * @author Caleb Fangmeier * @version 0.1 * * @section LICENSE * * * MIT License * * Copyright (c) 2017 Caleb Fangmeier * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * @section DESCRIPTION * This is the main api for FilVal. Users should try to avoid instantiating * Value objects directly, but rather use these functions. There are multiple * reasons for this. First of all, these functions do the extra work of making * sure that an identical Value doesn't already exist. If one does, it returns * the old Value object rather than creating a new one. The second reason is * that C++ allows type deduction for functions so one can often leave out the * type definitions to produce shorter, more readable, code. This cannot be * done when creating templated objects directly. */ #ifndef API_HPP #define API_HPP #include #include #include "filval/value.hpp" namespace fv{ template Value* lookup(const std::string& name){ Value* tv = GenValue::get_value(name); if (tv == nullptr){ CRITICAL("Could not find alias or value \"" << name << "\"." <<" I'll tell you the ones I know about." << std::endl << GenValue::summary(), -1); } return tv; } template Function* lookup_function(const std::string& name){ return GenFunction::lookup_function(name); } template bool check_exists(const std::string name){ Value* tv = GenValue::get_value(name); return tv != nullptr; } ObsFilter* lookup_obs_filter(const std::string& name){ ObsFilter* f = dynamic_cast(GenValue::get_value(name)); if(f == nullptr){ CRITICAL("ObsFilter: "+f->get_name() + "has improper type.",-1); } return f; } template decltype(auto) wrapper_vector(Value* size, Value* data, const std::string& alias=""){ typedef std::vector type; const std::string& name = WrapperVector::fmt_name(size, data); if (check_exists(name)) return lookup(name); else return (Value*)new WrapperVector(size, data, alias); } template decltype(auto) zip(Value>*... args, const std::string& alias=""){ typedef std::vector> type; std::string& name = Zip::fmt_name(args...); if (check_exists(name)) return lookup(name); else return (Value*)new Zip(args..., alias); } template decltype(auto) map(Function* fn, Value>* arg, const std::string& alias=""){ typedef std::vector type; const std::string& name = Map::fmt_name(fn, arg); if (check_exists(name)) return lookup(name); else return (Value*)new Map(fn, arg, alias); } template decltype(auto) tup_map(Function* fn, Value>>* arg, const std::string& alias=""){ typedef std::vector type; const std::string& name = TupMap::fmt_name(fn, arg); if (check_exists(name)) return lookup(name); else return (Value*)new TupMap(fn, arg, alias); } template decltype(auto) tuple(Value*... args){ typedef std::tuple type; const std::string& name = Tuple::fmt_name(args...); if (check_exists(name)) return lookup(name); else return (Value*)new Tuple(args..., ""); } template decltype(auto) detup(Value>* tup, const std::string& alias=""){ typedef typename std::tuple_element>::type type; const std::string& name = DeTup::fmt_name(tup); if (check_exists(name)) return lookup(name); else return (Value*)new DeTup(tup, alias); } template decltype(auto) detup_vec(Value>>* tup, const std::string& alias=""){ typedef std::vector>::type> type; const std::string& name = DeTupVector::fmt_name(tup); if (check_exists(name)) return lookup(name); else return (Value*)new DeTupVector(tup, alias); } template decltype(auto) apply(Function* fn, Value* arg, const std::string& alias=""){ typedef Ret type; const std::string& name = Apply::fmt_name(fn, arg); if (check_exists(name)) return lookup(name); else return (Value*)new Apply(fn, arg, alias); } template decltype(auto) tup_apply(Function* fn, Value>* arg, const std::string& alias=""){ typedef Ret type; const std::string& name = TupApply::fmt_name(fn, arg); if (check_exists(name)) return lookup(name); else return (Value*)new TupApply(fn, arg, alias); } template decltype(auto) pair(Value* val1, Value* val2, const std::string& alias=""){ typedef std::pair type; const std::string& name = Pair::fmt_name(val1, val2); if (check_exists(name)) return lookup(name); else return (Value*)new Pair(val1, val2, alias); } template decltype(auto) pair(const std::string& name1, const std::string& name2, const std::string& alias=""){ return pair(lookup(name1), lookup(name2), alias); } template decltype(auto) reduce(Function)>* fn, Value>* v, const std::string& alias=""){ typedef T type; const std::string& name = Reduce::fmt_name(fn, v); if (check_exists(name)) return lookup(name); else return (Value*)new Reduce(fn, v, alias); } template decltype(auto) max(Value>* v, const std::string& alias=""){ typedef T type; const std::string& name = Max::fmt_name(v); if (check_exists(name)) return lookup(name); else return (Value*)new Max(v, alias); } template decltype(auto) max(const std::string& v_name, const std::string& alias=""){ return max(lookup>(v_name), alias); } template decltype(auto) min(Value>* v, const std::string& alias=""){ typedef T type; const std::string& name = Min::fmt_name(v); if (check_exists(name)) return lookup(name); else return (Value*)new Min(v, alias); } template decltype(auto) min(const std::string& v_name, const std::string& alias=""){ return min(lookup>(v_name), alias); } template decltype(auto) range(Value>* v, const std::string& alias=""){ typedef T type; const std::string& name = Range::fmt_name(v); if (check_exists(name)) return lookup(name); else return (Value*)new Range(v, alias); } template decltype(auto) range(const std::string& v_name, const std::string& alias=""){ return range(lookup>(v_name), alias); } template decltype(auto) mean(Value>* v, const std::string& alias=""){ typedef T type; const std::string& name = Mean::fmt_name(v); if (check_exists(name)) return lookup(name); else return (Value*)new Mean(v, alias); } template decltype(auto) mean(const std::string& v_name, const std::string& alias=""){ return mean(lookup>(v_name), alias); } template decltype(auto) count(Function* selector, Value>* v, const std::string& alias=""){ typedef int type; const std::string& name = Count::fmt_name(selector, v); if (check_exists(name)) return lookup(name); else return (Value*)new Count(selector, v, alias); } template decltype(auto) count(Function* selector, const std::string& v_name, const std::string& alias=""){ return count(selector, lookup>(v_name), alias); } template decltype(auto) cart_product(Value>* val1, Value>* val2, const std::string& alias=""){ typedef std::vector> type; const std::string& name = CartProduct::fmt_name(val1, val2); if (check_exists(name)) return lookup(name); else return (Value*)new CartProduct(val1, val2, alias); } template decltype(auto) cart_product(const std::string& val1_name, const std::string& val2_name, const std::string& alias=""){ return cart_product(lookup>(val1_name), lookup>(val2_name), alias); } template decltype(auto) combinations(Value>* val, const std::string& alias=""){ typedef std::vector::type> type; const std::string& name = Combinations::fmt_name(val); if (check_exists(name)) return lookup(name); else return (Value*)new Combinations(val, alias); } template decltype(auto) combinations(const std::string& val_name, const std::string alias = ""){ return combinations(lookup>(val_name), alias); } template < typename T> decltype(auto) constant(const std::string name, T const_value, const std::string alias=""){ typedef T type; const std::string& val_name = ConstantValue::fmt_name(name); if (check_exists(val_name)) return lookup(val_name); else return (Value*)new ConstantValue(val_name, const_value, alias); } template decltype(auto) bound(Function* f, const std::string alias=""){ typedef T type; const std::string& name = BoundValue::fmt_name(f); if (check_exists(name)) return lookup(name); else return (Value*)new BoundValue(f, alias); } template decltype(auto) filter(Function* filter, Value>* val, const std::string alias=""){ typedef std::vector type; const std::string& name = Filter::fmt_name(filter, val); if (check_exists(name)) return lookup(name); else return (Value*)new Filter(filter, val, alias); } template decltype(auto) filter(Function* filter_func, const std::string& val_name, const std::string alias=""){ return filter(filter_func, lookup>(val_name), alias); } template decltype(auto) tup_filter(Function* filter, Value>>* val, const std::string alias=""){ typedef std::vector> type; const std::string& name = TupFilter::fmt_name(filter, val); if (check_exists(name)) return lookup(name); else return (Value*)new TupFilter(filter, val, alias); } template decltype(auto) tup_filter(Function* filter, const std::string& val_name, const std::string alias=""){ return tup_filter(filter, lookup>>(val_name), alias); } ObsFilter* obs_filter(const std::string& name, std::function filter_function, const std::string& impl=""){ return new ObsFilter(name, filter_function, impl); } template static Function* func(const std::string& name, std::function f, const std::string& impl){ return GenFunction::reg_func(name, f, impl); } template decltype(auto) func_value(const std::string& name, std::function f, const std::string&& impl, const std::string& alias=""){ typedef Ret type; const std::string& val_name = FunctionValue::fmt_name(name); if (check_exists(val_name)) return lookup(val_name); else { Function* fn = func(name, f, impl); return (Value*)new FunctionValue(name, fn, alias); } } } #endif // API_HPP