Path: blob/21.2-virgl/src/gallium/frontends/clover/util/algorithm.hpp
4572 views
//1// Copyright 2013 Francisco Jerez2//3// Permission is hereby granted, free of charge, to any person obtaining a4// copy of this software and associated documentation files (the "Software"),5// to deal in the Software without restriction, including without limitation6// the rights to use, copy, modify, merge, publish, distribute, sublicense,7// and/or sell copies of the Software, and to permit persons to whom the8// Software is furnished to do so, subject to the following conditions:9//10// The above copyright notice and this permission notice shall be included in11// all copies or substantial portions of the Software.12//13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR17// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19// OTHER DEALINGS IN THE SOFTWARE.20//2122#ifndef CLOVER_UTIL_ALGORITHM_HPP23#define CLOVER_UTIL_ALGORITHM_HPP2425#include <algorithm>26#include <sstream>27#include <stdexcept>2829#include "util/range.hpp"30#include "util/functional.hpp"3132namespace clover {33namespace detail {34template<typename R>35using preferred_reference_type = decltype(*std::declval<R>().begin());36}3738///39/// Return the first element in a range.40///41template<typename R>42detail::preferred_reference_type<R>43head(R &&r) {44assert(!r.empty());45return r.front();46}4748///49/// Return all elements in a range but the first.50///51template<typename R>52slice_range<R>53tail(R &&r) {54assert(!r.empty());55return { std::forward<R>(r), 1, r.size() };56}5758///59/// Return the only element in a range.60///61template<typename R>62detail::preferred_reference_type<R>63unique(R &&r) {64if (r.size() != 1)65throw std::out_of_range("");6667return r.front();68}6970///71/// Combine a variable number of ranges element-wise in a single72/// range of tuples.73///74template<typename... Rs>75adaptor_range<zips, Rs...>76zip(Rs &&... rs) {77return map(zips(), std::forward<Rs>(rs)...);78}7980///81/// Evaluate the elements of a range.82///83/// Useful because most of the range algorithms evaluate their84/// result lazily.85///86template<typename R>87void88eval(R &&r) {89for (auto i = r.begin(), e = r.end(); i != e; ++i)90*i;91}9293///94/// Apply functor \a f element-wise on a variable number of ranges95/// \a rs.96///97/// The functor \a f should take as many arguments as ranges are98/// provided.99///100template<typename F, typename... Rs>101void102for_each(F &&f, Rs &&... rs) {103eval(map(std::forward<F>(f), std::forward<Rs>(rs)...));104}105106///107/// Copy all elements from range \a r into an output container108/// starting from iterator \a i.109///110template<typename R, typename I>111void112copy(R &&r, I i) {113for (detail::preferred_reference_type<R> x : r)114*(i++) = x;115}116117///118/// Reduce the elements of range \a r by applying functor \a f119/// element by element.120///121/// \a f should take an accumulator value (which is initialized to122/// \a a) and an element value as arguments, and return an updated123/// accumulator value.124///125/// \returns The final value of the accumulator.126///127template<typename F, typename A, typename R>128A129fold(F &&f, A a, R &&r) {130for (detail::preferred_reference_type<R> x : r)131a = f(a, x);132133return a;134}135136///137/// Return how many elements of range \a r are equal to \a x.138///139template<typename T, typename R>140typename std::remove_reference<R>::type::size_type141count(T &&x, R &&r) {142typename std::remove_reference<R>::type::size_type n = 0;143144for (detail::preferred_reference_type<R> y : r) {145if (x == y)146n++;147}148149return n;150}151152///153/// Return the first element in range \a r for which predicate \a f154/// evaluates to true.155///156template<typename F, typename R>157detail::preferred_reference_type<R>158find(F &&f, R &&r) {159for (detail::preferred_reference_type<R> x : r) {160if (f(x))161return x;162}163164throw std::out_of_range("");165}166167///168/// Return true if the element-wise application of predicate \a f169/// on \a rs evaluates to true for all elements.170///171template<typename F, typename... Rs>172bool173all_of(F &&f, Rs &&... rs) {174for (auto b : map(f, rs...)) {175if (!b)176return false;177}178179return true;180}181182///183/// Return true if the element-wise application of predicate \a f184/// on \a rs evaluates to true for any element.185///186template<typename F, typename... Rs>187bool188any_of(F &&f, Rs &&... rs) {189for (auto b : map(f, rs...)) {190if (b)191return true;192}193194return false;195}196197///198/// Erase elements for which predicate \a f evaluates to true from199/// container \a r.200///201template<typename F, typename R>202void203erase_if(F &&f, R &&r) {204auto i = r.begin(), e = r.end();205206for (auto j = r.begin(); j != e; ++j) {207if (!f(*j)) {208if (j != i)209*i = std::move(*j);210++i;211}212}213214r.erase(i, e);215}216217///218/// Build a vector of string from a space separated string219/// quoted parts content is preserved and unquoted220///221inline std::vector<std::string>222tokenize(const std::string &s) {223std::vector<std::string> ss;224std::ostringstream oss;225226// OpenCL programs can pass a quoted argument, most frequently the227// include path. This is useful so that path containing spaces is228// treated as a single argument instead of being split by the spaces.229// Additionally, the argument should also be unquoted before being230// passed to the compiler. We avoid using std::string::replace here to231// remove quotes, as the single and double quote characters can be a232// part of the file name.233bool escape_next = false;234bool in_quote_double = false;235bool in_quote_single = false;236237for (auto c : s) {238if (escape_next) {239oss.put(c);240escape_next = false;241} else if (c == '\\') {242escape_next = true;243} else if (c == '"' && !in_quote_single) {244in_quote_double = !in_quote_double;245} else if (c == '\'' && !in_quote_double) {246in_quote_single = !in_quote_single;247} else if (c != ' ' || in_quote_single || in_quote_double) {248oss.put(c);249} else if (oss.tellp() > 0) {250ss.emplace_back(oss.str());251oss.str("");252}253}254255if (oss.tellp() > 0)256ss.emplace_back(oss.str());257258if (in_quote_double || in_quote_single)259throw invalid_build_options_error();260261return ss;262}263264///265/// Build a \a sep separated string from a vector of T266///267template<typename T>268std::string269detokenize(const std::vector<T> &ss, const std::string &sep) {270std::string r;271272for (const auto &s : ss)273r += (r.empty() ? "" : sep) + std::to_string(s);274275return r;276}277278///279/// Build a \a sep separated string from a vector of string280///281template <>282inline std::string283detokenize(const std::vector<std::string> &ss, const std::string &sep) {284std::string r;285286for (const auto &s : ss)287r += (r.empty() || s.empty() ? "" : sep) + s;288289return r;290}291}292293#endif294295296