source: src/Common/utility.h @ ed52dd5

ADTast-experimental
Last change on this file since ed52dd5 was 8f06277, checked in by Andrew Beach <ajbeach@…>, 17 months ago

Some clean-up in Common/utility.h. Deleted some unused declarations and moved others to one of two new headers.

  • Property mode set to 100644
File size: 7.4 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// utility.h -- General utilities used across the compiler.
8//
9// Author           : Richard C. Bilson
10// Created On       : Mon May 18 07:44:20 2015
11// Last Modified By : Andrew Beach
12// Last Modified On : Fri Feb 17 15:25:00 2023
13// Update Count     : 53
14//
15
16#pragma once
17
18#include <cassert>
19#include <cctype>
20#include <algorithm>
21#include <iostream>
22#include <list>
23#include <memory>
24#include <sstream>
25#include <string>
26#include <type_traits>
27#include <vector>
28#include <cstring>                                                                              // memcmp
29
30#include "Common/Indenter.h"
31
32class Expression;
33
34/// bring std::move into global scope
35using std::move;
36
37/// partner to move that copies any copyable type
38template<typename T>
39T copy( const T & x ) { return x; }
40
41template< typename T >
42static inline T * maybeClone( const T *orig ) {
43        if ( orig ) {
44                return orig->clone();
45        } else {
46                return 0;
47        } // if
48}
49
50template< typename Input_iterator >
51void printEnums( Input_iterator begin, Input_iterator end, const char * const *name_array, std::ostream &os ) {
52        for ( Input_iterator i = begin; i != end; ++i ) {
53                os << name_array[ *i ] << ' ';
54        } // for
55}
56
57template< typename Container >
58void deleteAll( const Container &container ) {
59        for ( const auto &i : container ) {
60                delete i;
61        } // for
62}
63
64template< typename Container >
65void printAll( const Container &container, std::ostream &os, Indenter indent = {} ) {
66        for ( typename Container::const_iterator i = container.begin(); i != container.end(); ++i ) {
67                if ( *i ) {
68                        os << indent;
69                        (*i)->print( os, indent );
70                        // need an endl after each element because it's not easy to know when each individual item should end
71                        os << std::endl;
72                } // if
73        } // for
74}
75
76template< typename SrcContainer, typename DestContainer >
77void cloneAll( const SrcContainer &src, DestContainer &dest ) {
78        typename SrcContainer::const_iterator in = src.begin();
79        std::back_insert_iterator< DestContainer > out( dest );
80        while ( in != src.end() ) {
81                *out++ = (*in++)->clone();
82        } // while
83}
84
85template< typename SrcContainer, typename DestContainer, typename Predicate >
86void cloneAll_if( const SrcContainer &src, DestContainer &dest, Predicate pred ) {
87        std::back_insert_iterator< DestContainer > out( dest );
88        for ( auto x : src ) {
89                if ( pred(x) ) {
90                        *out++ = x->clone();
91                }
92        } // while
93}
94
95template< typename Container >
96void assertAll( const Container &container ) {
97        int count = 0;
98        for ( typename Container::const_iterator i = container.begin(); i != container.end(); ++i ) {
99                if ( !(*i) ) {
100                        std::cerr << count << " is null" << std::endl;
101                } // if
102        } // for
103}
104
105template < typename T >
106std::list<T> tail( std::list<T> l ) {
107        if ( ! l.empty() ) {
108                std::list<T> ret(++(l.begin()), l.end());
109                return ret;
110        } // if
111}
112
113template < typename T >
114std::list<T> flatten( std::list < std::list<T> > l) {
115        typedef std::list <T> Ts;
116
117        Ts ret;
118
119        switch ( l.size() ) {
120          case 0:
121                return ret;
122          case 1:
123                return l.front();
124          default:
125                ret = flatten(tail(l));
126                ret.insert(ret.begin(), l.front().begin(), l.front().end());
127                return ret;
128        } // switch
129}
130
131/// Splice src onto the end of dst, clearing src
132template< typename T >
133void splice( std::vector< T > & dst, std::vector< T > & src ) {
134        dst.reserve( dst.size() + src.size() );
135        for ( T & x : src ) { dst.emplace_back( std::move( x ) ); }
136        src.clear();
137}
138
139/// Splice src onto the begining of dst, clearing src
140template< typename T >
141void spliceBegin( std::vector< T > & dst, std::vector< T > & src ) {
142        splice( src, dst );
143        dst.swap( src );
144}
145
146template < typename T >
147void toString_single( std::ostream & os, const T & value ) {
148        os << value;
149}
150
151template < typename T, typename... Params >
152void toString_single( std::ostream & os, const T & value, const Params & ... params ) {
153        os << value;
154        toString_single( os, params ... );
155}
156
157template < typename ... Params >
158std::string toString( const Params & ... params ) {
159        std::ostringstream os;
160        toString_single( os, params... );
161        return os.str();
162}
163
164#define toCString( ... ) toString( __VA_ARGS__ ).c_str()
165
166template< typename... Args >
167auto filter(Args&&... args) -> decltype(std::copy_if(std::forward<Args>(args)...)) {
168  return std::copy_if(std::forward<Args>(args)...);
169}
170
171template <typename E, typename UnaryPredicate, template< typename, typename...> class Container, typename... Args >
172void filter( Container< E *, Args... > & container, UnaryPredicate pred, bool doDelete ) {
173        auto i = begin( container );
174        while ( i != end( container ) ) {
175                auto it = next( i );
176                if ( pred( *i ) ) {
177                        if ( doDelete ) {
178                                delete *i;
179                        } // if
180                        container.erase( i );
181                } // if
182                i = it;
183        } // while
184}
185
186template<typename Container, typename Pred>
187void erase_if( Container & cont, Pred && pred ) {
188        auto keep_end = std::remove_if( cont.begin(), cont.end(), pred );
189        cont.erase( keep_end, cont.end() );
190}
191
192template< typename... Params >
193void warn( const Params & ... params ) {
194        std::cerr << "Warning: ";
195        toString_single( std::cerr, params... );
196        std::cerr << std::endl;
197}
198
199// determines if pref is a prefix of str
200static inline bool isPrefix( const std::string & str, const std::string & pref, unsigned int start = 0 ) {
201        if ( pref.size() > str.size() ) return false;
202        return pref == str.substr(start, pref.size());
203}
204
205// -----------------------------------------------------------------------------
206// RAII object to regulate "save and restore" behaviour, e.g.
207// void Foo::bar() {
208//   ValueGuard<int> guard(var); // var is a member of type Foo
209//   var = ...;
210// } // var's original value is restored
211template< typename T >
212struct ValueGuard {
213        T old;
214        T& ref;
215
216        ValueGuard(T& inRef) : old(inRef), ref(inRef) {}
217        ~ValueGuard() { ref = old; }
218};
219
220template< typename T >
221struct ValueGuardPtr {
222        T old;
223        T* ref;
224
225        ValueGuardPtr(T * inRef) : old( inRef ? *inRef : T() ), ref(inRef) {}
226        ValueGuardPtr(const ValueGuardPtr& other) = delete;
227        ValueGuardPtr(ValueGuardPtr&& other) : old(other.old), ref(other.ref) { other.ref = nullptr; }
228        ~ValueGuardPtr() { if( ref ) *ref = old; }
229};
230
231template< typename aT >
232struct FuncGuard {
233        aT m_after;
234
235        template< typename bT >
236        FuncGuard( bT before, aT after ) : m_after( after ) {
237                before();
238        }
239
240        ~FuncGuard() {
241                m_after();
242        }
243};
244
245template< typename bT, typename aT >
246FuncGuard<aT> makeFuncGuard( bT && before, aT && after ) {
247        return FuncGuard<aT>( std::forward<bT>(before), std::forward<aT>(after) );
248}
249
250template< typename T >
251struct ValueGuardPtr< std::list< T > > {
252        std::list< T > old;
253        std::list< T >* ref;
254
255        ValueGuardPtr( std::list< T > * inRef) : old(), ref(inRef) {
256                if( ref ) { swap( *ref, old ); }
257        }
258        ~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } }
259};
260
261// -----------------------------------------------------------------------------
262// O(1) polymorphic integer ilog2, using clz, which returns the number of leading 0-bits, starting at the most
263// significant bit (single instruction on x86)
264
265template<typename T>
266inline
267#if defined(__GNUC__) && __GNUC__ > 4
268constexpr
269#endif
270T ilog2(const T & t) {
271        if(std::is_integral<T>::value) {
272                const constexpr int r = sizeof(t) * __CHAR_BIT__ - 1;
273                if( sizeof(T) == sizeof(unsigned       int) ) return r - __builtin_clz  ( t );
274                if( sizeof(T) == sizeof(unsigned      long) ) return r - __builtin_clzl ( t );
275                if( sizeof(T) == sizeof(unsigned long long) ) return r - __builtin_clzll( t );
276        }
277        assert(false);
278        return -1;
279} // ilog2
280
281// Local Variables: //
282// tab-width: 4 //
283// mode: c++ //
284// compile-command: "make install" //
285// End: //
Note: See TracBrowser for help on using the repository browser.