source: src/Common/utility.h @ 6b0b624

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newwith_gc
Last change on this file since 6b0b624 was 6b0b624, checked in by Peter A. Buhr <pabuhr@…>, 4 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.