source: src/Common/utility.h@ ab6ed1e

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since ab6ed1e was 6b0b624, checked in by Peter A. Buhr <pabuhr@…>, 8 years ago

change #ifndef to #pragma once

  • Property mode set to 100644
File size: 10.0 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 --
8//
9// Author : Richard C. Bilson
10// Created On : Mon May 18 07:44:20 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Fri Jul 21 22:19:13 2017
13// Update Count : 33
14//
15
16#pragma once
17
18#include <cctype>
19#include <algorithm>
20#include <iostream>
21#include <iterator>
22#include <list>
23#include <memory>
24#include <sstream>
25#include <string>
26
27#include <cassert>
28template< typename T >
29static inline T * maybeClone( const T *orig ) {
30 if ( orig ) {
31 return orig->clone();
32 } else {
33 return 0;
34 } // if
35}
36
37template< typename T, typename U >
38struct maybeBuild_t {
39 static T * doit( const U *orig ) {
40 if ( orig ) {
41 return orig->build();
42 } else {
43 return 0;
44 } // if
45 }
46};
47
48template< typename T, typename U >
49static inline T * maybeBuild( const U *orig ) {
50 return maybeBuild_t<T,U>::doit(orig);
51}
52
53template< typename T, typename U >
54static inline T * maybeMoveBuild( const U *orig ) {
55 T* ret = maybeBuild<T>(orig);
56 delete orig;
57 return ret;
58}
59
60template< typename Input_iterator >
61void printEnums( Input_iterator begin, Input_iterator end, const char * const *name_array, std::ostream &os ) {
62 for ( Input_iterator i = begin; i != end; ++i ) {
63 os << name_array[ *i ] << ' ';
64 } // for
65}
66
67template< typename Container >
68void deleteAll( Container &container ) {
69 for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
70 delete *i;
71 } // for
72}
73
74template< typename Container >
75void printAll( const Container &container, std::ostream &os, int indent = 0 ) {
76 for ( typename Container::const_iterator i = container.begin(); i != container.end(); ++i ) {
77 if ( *i ) {
78 os << std::string( indent, ' ' );
79 (*i)->print( os, indent + 2 );
80 // need an endl after each element because it's not easy to know when each individual item should end
81 os << std::endl;
82 } // if
83 } // for
84}
85
86template< typename SrcContainer, typename DestContainer >
87void cloneAll( const SrcContainer &src, DestContainer &dest ) {
88 typename SrcContainer::const_iterator in = src.begin();
89 std::back_insert_iterator< DestContainer > out( dest );
90 while ( in != src.end() ) {
91 *out++ = (*in++)->clone();
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
131template < typename T >
132void toString_single( std::ostream & os, const T & value ) {
133 os << value;
134}
135
136template < typename T, typename... Params >
137void toString_single( std::ostream & os, const T & value, const Params & ... params ) {
138 os << value;
139 toString_single( os, params ... );
140}
141
142template < typename ... Params >
143std::string toString( const Params & ... params ) {
144 std::ostringstream os;
145 toString_single( os, params... );
146 return os.str();
147}
148
149// replace element of list with all elements of another list
150template< typename T >
151void replace( std::list< T > &org, typename std::list< T >::iterator pos, std::list< T > &with ) {
152 typename std::list< T >::iterator next = pos; advance( next, 1 );
153
154 //if ( next != org.end() ) {
155 org.erase( pos );
156 org.splice( next, with );
157 //}
158
159 return;
160}
161
162// replace range of a list with a single element
163template< typename T >
164void replace( std::list< T > &org, typename std::list< T >::iterator begin, typename std::list< T >::iterator end, const T & with ) {
165 org.insert( begin, with );
166 org.erase( begin, end );
167}
168
169template< typename... Args >
170auto filter(Args&&... args) -> decltype(std::copy_if(std::forward<Args>(args)...)) {
171 return std::copy_if(std::forward<Args>(args)...);
172}
173
174template< typename... Args >
175auto zip(Args&&... args) -> decltype(zipWith(std::forward<Args>(args)..., std::make_pair)) {
176 return zipWith(std::forward<Args>(args)..., std::make_pair);
177}
178
179template< class InputIterator1, class InputIterator2, class OutputIterator, class BinFunction >
180void zipWith( InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2, OutputIterator out, BinFunction func ) {
181 while ( b1 != e1 && b2 != e2 )
182 *out++ = func(*b1++, *b2++);
183}
184
185// it's nice to actually be able to increment iterators by an arbitrary amount
186template< class InputIt, class Distance >
187InputIt operator+( InputIt it, Distance n ) {
188 advance(it, n);
189 return it;
190}
191
192template< typename T >
193void warn_single( const T & arg ) {
194 std::cerr << arg << std::endl;
195}
196
197template< typename T, typename... Params >
198void warn_single(const T & arg, const Params & ... params ) {
199 std::cerr << arg;
200 warn_single( params... );
201}
202
203template< typename... Params >
204void warn( const Params & ... params ) {
205 std::cerr << "Warning: ";
206 warn_single( params... );
207}
208
209// -----------------------------------------------------------------------------
210// Ref Counted Singleton class
211// Objects that inherit from this class will have at most one reference to it
212// but if all references die, the object will be deleted.
213
214template< typename ThisType >
215class RefCountSingleton {
216 public:
217 static std::shared_ptr<ThisType> get() {
218 if( global_instance.expired() ) {
219 std::shared_ptr<ThisType> new_instance = std::make_shared<ThisType>();
220 global_instance = new_instance;
221 return std::move(new_instance);
222 }
223 return global_instance.lock();
224 }
225 private:
226 static std::weak_ptr<ThisType> global_instance;
227};
228
229template< typename ThisType >
230std::weak_ptr<ThisType> RefCountSingleton<ThisType>::global_instance;
231
232// -----------------------------------------------------------------------------
233// RAII object to regulate "save and restore" behaviour, e.g.
234// void Foo::bar() {
235// ValueGuard<int> guard(var); // var is a member of type Foo
236// var = ...;
237// } // var's original value is restored
238template< typename T >
239struct ValueGuard {
240 T old;
241 T& ref;
242
243 ValueGuard(T& inRef) : old(inRef), ref(inRef) {}
244 ~ValueGuard() { ref = old; }
245};
246
247template< typename T >
248struct ValueGuardPtr {
249 T old;
250 T* ref;
251
252 ValueGuardPtr(T * inRef) : old( inRef ? *inRef : T() ), ref(inRef) {}
253 ~ValueGuardPtr() { if( ref ) *ref = old; }
254};
255
256template< typename T >
257struct ValueGuardPtr< std::list< T > > {
258 std::list< T > old;
259 std::list< T >* ref;
260
261 ValueGuardPtr( std::list< T > * inRef) : old(), ref(inRef) {
262 if( ref ) { swap( *ref, old ); }
263 }
264 ~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } }
265};
266
267// -----------------------------------------------------------------------------
268// Helper struct and function to support
269// for ( val : reverseIterate( container ) ) {}
270// syntax to have a for each that iterates backwards
271
272template< typename T >
273struct reverse_iterate_t {
274 T& ref;
275
276 reverse_iterate_t( T & ref ) : ref(ref) {}
277
278 typedef typename T::reverse_iterator iterator;
279 iterator begin() { return ref.rbegin(); }
280 iterator end() { return ref.rend(); }
281};
282
283template< typename T >
284reverse_iterate_t< T > reverseIterate( T & ref ) {
285 return reverse_iterate_t< T >( ref );
286}
287
288template< typename OutType, typename Range, typename Functor >
289OutType map_range( const Range& range, Functor&& functor ) {
290 OutType out;
291
292 std::transform(
293 begin( range ),
294 end( range ),
295 std::back_inserter( out ),
296 std::forward< Functor >( functor )
297 );
298
299 return out;
300}
301
302// -----------------------------------------------------------------------------
303// Helper struct and function to support
304// for ( val : group_iterate( container1, container2, ... ) ) {}
305// syntax to have a for each that iterates multiple containers of the same length
306// TODO: update to use variadic arguments, perfect forwarding
307
308template< typename T1, typename T2 >
309struct group_iterate_t {
310 group_iterate_t( const T1 & v1, const T2 & v2 ) : args(v1, v2) {
311 assertf(v1.size() == v2.size(), "group iteration requires containers of the same size.");
312 };
313
314 struct iterator {
315 typedef std::tuple<typename T1::value_type, typename T2::value_type> value_type;
316 typedef typename T1::iterator T1Iter;
317 typedef typename T2::iterator T2Iter;
318 typedef std::tuple<T1Iter, T2Iter> IterTuple;
319 IterTuple it;
320 iterator( T1Iter i1, T2Iter i2 ) : it( i1, i2 ) {}
321 iterator operator++() {
322 return iterator( ++std::get<0>(it), ++std::get<1>(it) );
323 }
324 bool operator!=( const iterator &other ) const { return it != other.it; }
325 value_type operator*() const { return std::make_tuple( *std::get<0>(it), *std::get<1>(it) ); }
326 };
327 iterator begin() { return iterator( std::get<0>(args).begin(), std::get<1>(args).begin() ); }
328 iterator end() { return iterator( std::get<0>(args).end(), std::get<1>(args).end() ); }
329
330private:
331 std::tuple<T1, T2> args;
332};
333
334template< typename... Args >
335group_iterate_t<Args...> group_iterate( const Args &... args ) {
336 return group_iterate_t<Args...>(args...);
337}
338
339struct CodeLocation {
340 int linenumber;
341 std::string filename;
342
343 /// Create a new unset CodeLocation.
344 CodeLocation()
345 : linenumber( -1 )
346 , filename("")
347 {}
348
349 /// Create a new CodeLocation with the given values.
350 CodeLocation( const char* filename, int lineno )
351 : linenumber( lineno )
352 , filename(filename ? filename : "")
353 {}
354
355 CodeLocation( const CodeLocation& rhs ) = default;
356
357 bool isSet () const {
358 return -1 != linenumber;
359 }
360
361 bool isUnset () const {
362 return !isSet();
363 }
364
365 void unset () {
366 linenumber = -1;
367 filename = "";
368 }
369
370 // Use field access for set.
371};
372
373inline std::string to_string( const CodeLocation& location ) {
374 return location.isSet() ? location.filename + ":" + std::to_string(location.linenumber) + " " : "";
375}
376
377// Local Variables: //
378// tab-width: 4 //
379// mode: c++ //
380// compile-command: "make install" //
381// End: //
Note: See TracBrowser for help on using the repository browser.