source: src/Common/utility.h@ 640b3df

ADT ast-experimental
Last change on this file since 640b3df was 8f06277, checked in by Andrew Beach <ajbeach@…>, 3 years 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.