Changes in src/Common/utility.h [9feb34b:7491f97]
- File:
-
- 1 edited
-
src/Common/utility.h (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Common/utility.h
r9feb34b r7491f97 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // utility.h -- General utilities used across the compiler.7 // utility.h -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Feb 17 15:25:00 202313 // Update Count : 5 312 // Last Modified On : Mon Apr 25 14:26:00 2022 13 // Update Count : 51 14 14 // 15 15 … … 19 19 #include <cctype> 20 20 #include <algorithm> 21 #include <functional> 21 22 #include <iostream> 23 #include <iterator> 22 24 #include <list> 23 25 #include <memory> 26 #include <sstream> 24 27 #include <string> 25 28 #include <type_traits> 29 #include <utility> 26 30 #include <vector> 27 31 #include <cstring> // memcmp … … 45 49 return 0; 46 50 } // if 51 } 52 53 template< typename T, typename U > 54 struct maybeBuild_t { 55 static T * doit( const U *orig ) { 56 if ( orig ) { 57 return orig->build(); 58 } else { 59 return 0; 60 } // if 61 } 62 }; 63 64 template< typename T, typename U > 65 static inline T * maybeBuild( const U *orig ) { 66 return maybeBuild_t<T,U>::doit(orig); 67 } 68 69 template< typename T, typename U > 70 static inline T * maybeMoveBuild( const U *orig ) { 71 T* ret = maybeBuild<T>(orig); 72 delete orig; 73 return ret; 47 74 } 48 75 … … 141 168 splice( src, dst ); 142 169 dst.swap( src ); 170 } 171 172 template < typename T > 173 void toString_single( std::ostream & os, const T & value ) { 174 os << value; 175 } 176 177 template < typename T, typename... Params > 178 void toString_single( std::ostream & os, const T & value, const Params & ... params ) { 179 os << value; 180 toString_single( os, params ... ); 181 } 182 183 template < typename ... Params > 184 std::string toString( const Params & ... params ) { 185 std::ostringstream os; 186 toString_single( os, params... ); 187 return os.str(); 188 } 189 190 #define toCString( ... ) toString( __VA_ARGS__ ).c_str() 191 192 // replace element of list with all elements of another list 193 template< typename T > 194 void replace( std::list< T > &org, typename std::list< T >::iterator pos, std::list< T > &with ) { 195 typename std::list< T >::iterator next = pos; advance( next, 1 ); 196 197 //if ( next != org.end() ) { 198 org.erase( pos ); 199 org.splice( next, with ); 200 //} 201 202 return; 203 } 204 205 // replace range of a list with a single element 206 template< typename T > 207 void replace( std::list< T > &org, typename std::list< T >::iterator begin, typename std::list< T >::iterator end, const T & with ) { 208 org.insert( begin, with ); 209 org.erase( begin, end ); 143 210 } 144 211 … … 169 236 } 170 237 238 template< typename... Args > 239 auto zip(Args&&... args) -> decltype(zipWith(std::forward<Args>(args)..., std::make_pair)) { 240 return zipWith(std::forward<Args>(args)..., std::make_pair); 241 } 242 243 template< class InputIterator1, class InputIterator2, class OutputIterator, class BinFunction > 244 void zipWith( InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2, OutputIterator out, BinFunction func ) { 245 while ( b1 != e1 && b2 != e2 ) 246 *out++ = func(*b1++, *b2++); 247 } 248 249 // it's nice to actually be able to increment iterators by an arbitrary amount 250 template< class InputIt, class Distance > 251 InputIt operator+( InputIt it, Distance n ) { 252 advance(it, n); 253 return it; 254 } 255 256 template< typename T > 257 void warn_single( const T & arg ) { 258 std::cerr << arg << std::endl; 259 } 260 261 template< typename T, typename... Params > 262 void warn_single(const T & arg, const Params & ... params ) { 263 std::cerr << arg; 264 warn_single( params... ); 265 } 266 267 template< typename... Params > 268 void warn( const Params & ... params ) { 269 std::cerr << "Warning: "; 270 warn_single( params... ); 271 } 272 171 273 // determines if pref is a prefix of str 172 274 static inline bool isPrefix( const std::string & str, const std::string & pref, unsigned int start = 0 ) { 173 275 if ( pref.size() > str.size() ) return false; 174 return pref == str.substr(start, pref.size()); 175 } 276 return 0 == memcmp( str.c_str() + start, pref.c_str(), pref.size() ); 277 // return prefix == full.substr(0, prefix.size()); // for future, requires c++17 278 } 279 280 // ----------------------------------------------------------------------------- 281 // Ref Counted Singleton class 282 // Objects that inherit from this class will have at most one reference to it 283 // but if all references die, the object will be deleted. 284 285 template< typename ThisType > 286 class RefCountSingleton { 287 public: 288 static std::shared_ptr<ThisType> get() { 289 if( global_instance.expired() ) { 290 std::shared_ptr<ThisType> new_instance = std::make_shared<ThisType>(); 291 global_instance = new_instance; 292 return std::move(new_instance); 293 } 294 return global_instance.lock(); 295 } 296 private: 297 static std::weak_ptr<ThisType> global_instance; 298 }; 299 300 template< typename ThisType > 301 std::weak_ptr<ThisType> RefCountSingleton<ThisType>::global_instance; 176 302 177 303 // ----------------------------------------------------------------------------- … … 230 356 ~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } } 231 357 }; 358 359 // ----------------------------------------------------------------------------- 360 // Helper struct and function to support 361 // for ( val : reverseIterate( container ) ) {} 362 // syntax to have a for each that iterates backwards 363 364 template< typename T > 365 struct reverse_iterate_t { 366 T& ref; 367 368 reverse_iterate_t( T & ref ) : ref(ref) {} 369 370 // this does NOT work on const T!!! 371 // typedef typename T::reverse_iterator iterator; 372 auto begin() { return ref.rbegin(); } 373 auto end() { return ref.rend(); } 374 }; 375 376 template< typename T > 377 reverse_iterate_t< T > reverseIterate( T & ref ) { 378 return reverse_iterate_t< T >( ref ); 379 } 380 381 template< typename T > 382 struct enumerate_t { 383 template<typename val_t> 384 struct value_t { 385 val_t & val; 386 size_t idx; 387 }; 388 389 template< typename iter_t, typename val_t > 390 struct iterator_t { 391 iter_t it; 392 size_t idx; 393 394 iterator_t( iter_t _it, size_t _idx ) : it(_it), idx(_idx) {} 395 396 value_t<val_t> operator*() const { return value_t<val_t>{ *it, idx }; } 397 398 bool operator==(const iterator_t & o) const { return o.it == it; } 399 bool operator!=(const iterator_t & o) const { return o.it != it; } 400 401 iterator_t & operator++() { 402 it++; 403 idx++; 404 return *this; 405 } 406 407 using difference_type = typename std::iterator_traits< iter_t >::difference_type; 408 using value_type = value_t<val_t>; 409 using pointer = value_t<val_t> *; 410 using reference = value_t<val_t> &; 411 using iterator_category = std::forward_iterator_tag; 412 }; 413 414 T & ref; 415 416 using iterator = iterator_t< typename T::iterator, typename T::value_type >; 417 using const_iterator = iterator_t< typename T::const_iterator, const typename T::value_type >; 418 419 iterator begin() { return iterator( ref.begin(), 0 ); } 420 iterator end() { return iterator( ref.end(), ref.size() ); } 421 422 const_iterator begin() const { return const_iterator( ref.cbegin(), 0 ); } 423 const_iterator end() const { return const_iterator( ref.cend(), ref.size() ); } 424 425 const_iterator cbegin() const { return const_iterator( ref.cbegin(), 0 ); } 426 const_iterator cend() const { return const_iterator( ref.cend(), ref.size() ); } 427 }; 428 429 template< typename T > 430 enumerate_t<T> enumerate( T & ref ) { 431 return enumerate_t< T >{ ref }; 432 } 433 434 template< typename T > 435 const enumerate_t< const T > enumerate( const T & ref ) { 436 return enumerate_t< const T >{ ref }; 437 } 438 439 template< typename OutType, typename Range, typename Functor > 440 OutType map_range( const Range& range, Functor&& functor ) { 441 OutType out; 442 443 std::transform( 444 begin( range ), 445 end( range ), 446 std::back_inserter( out ), 447 std::forward< Functor >( functor ) 448 ); 449 450 return out; 451 } 452 453 // ----------------------------------------------------------------------------- 454 // Helper struct and function to support: 455 // for ( auto val : group_iterate( container1, container2, ... ) ) { ... } 456 // This iteraters through multiple containers of the same size. 457 458 template<typename... Args> 459 class group_iterate_t { 460 using Iterables = std::tuple<Args...>; 461 Iterables iterables; 462 463 // Getting the iterator and value types this way preserves const. 464 template<size_t I> using Iter = decltype(std::get<I>(iterables).begin()); 465 template<size_t I> using Data = decltype(*std::get<I>(iterables).begin()); 466 template<typename> struct base_iterator; 467 468 // This inner template puts the sequence of `0, 1, ... sizeof...(Args)-1` 469 // into a pack. These are the indexes into the tuples, so unpacking can 470 // go over each element of the tuple. 471 // The std::integer_sequence is just used to build that sequence. 472 // A library reference will probably explain it better than I can. 473 template<std::size_t... Indices> 474 struct base_iterator<std::integer_sequence<std::size_t, Indices...>> { 475 using value_type = std::tuple< Data<Indices>... >; 476 std::tuple<Iter<Indices>...> iterators; 477 478 base_iterator( Iter<Indices>... is ) : iterators( is... ) {} 479 base_iterator operator++() { 480 return base_iterator( ++std::get<Indices>( iterators )... ); 481 } 482 bool operator!=( const base_iterator& other ) const { 483 return iterators != other.iterators; 484 } 485 value_type operator*() const { 486 return std::tie( *std::get<Indices>( iterators )... ); 487 } 488 489 static base_iterator make_begin( Iterables & data ) { 490 return base_iterator( std::get<Indices>( data ).begin()... ); 491 } 492 static base_iterator make_end( Iterables & data ) { 493 return base_iterator( std::get<Indices>( data ).end()... ); 494 } 495 }; 496 497 public: 498 group_iterate_t( const Args &... args ) : iterables( args... ) {} 499 500 using iterator = base_iterator<decltype( 501 std::make_integer_sequence<std::size_t, sizeof...(Args)>())>; 502 503 iterator begin() { return iterator::make_begin( iterables ); } 504 iterator end() { return iterator::make_end( iterables ); } 505 }; 506 507 // Helpers for the bounds checks (the non-varatic part of group_iterate): 508 static inline void runGroupBoundsCheck(size_t size0, size_t size1) { 509 assertf( size0 == size1, 510 "group iteration requires containers of the same size: <%zd, %zd>.", 511 size0, size1 ); 512 } 513 514 static inline void runGroupBoundsCheck(size_t size0, size_t size1, size_t size2) { 515 assertf( size0 == size1 && size1 == size2, 516 "group iteration requires containers of the same size: <%zd, %zd, %zd>.", 517 size0, size1, size2 ); 518 } 519 520 /// Performs bounds check to ensure that all arguments are of the same length. 521 template< typename... Args > 522 group_iterate_t<Args...> group_iterate( Args &&... args ) { 523 runGroupBoundsCheck( args.size()... ); 524 return group_iterate_t<Args...>( std::forward<Args>( args )... ); 525 } 526 527 /// Does not perform a bounds check - requires user to ensure that iteration terminates when appropriate. 528 template< typename... Args > 529 group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) { 530 return group_iterate_t<Args...>( std::forward<Args>( args )... ); 531 } 532 533 // ----------------------------------------------------------------------------- 534 // Helper struct and function to support 535 // for ( val : lazy_map( container1, f ) ) {} 536 // syntax to have a for each that iterates a container, mapping each element by applying f 537 template< typename T, typename Func > 538 struct lambda_iterate_t { 539 const T & ref; 540 std::function<Func> f; 541 542 struct iterator { 543 typedef decltype(begin(ref)) Iter; 544 Iter it; 545 std::function<Func> f; 546 iterator( Iter it, std::function<Func> f ) : it(it), f(f) {} 547 iterator & operator++() { 548 ++it; return *this; 549 } 550 bool operator!=( const iterator &other ) const { return it != other.it; } 551 auto operator*() const -> decltype(f(*it)) { return f(*it); } 552 }; 553 554 lambda_iterate_t( const T & ref, std::function<Func> f ) : ref(ref), f(f) {} 555 556 auto begin() const -> decltype(iterator(std::begin(ref), f)) { return iterator(std::begin(ref), f); } 557 auto end() const -> decltype(iterator(std::end(ref), f)) { return iterator(std::end(ref), f); } 558 }; 559 560 template< typename... Args > 561 lambda_iterate_t<Args...> lazy_map( const Args &... args ) { 562 return lambda_iterate_t<Args...>( args...); 563 } 232 564 233 565 // ----------------------------------------------------------------------------- … … 251 583 } // ilog2 252 584 585 // ----------------------------------------------------------------------------- 586 /// evaluates expr as a long long int. If second is false, expr could not be evaluated 587 std::pair<long long int, bool> eval(const Expression * expr); 588 589 namespace ast { 590 class Expr; 591 } 592 593 std::pair<long long int, bool> eval(const ast::Expr * expr); 594 595 // ----------------------------------------------------------------------------- 596 /// Reorders the input range in-place so that the minimal-value elements according to the 597 /// comparator are in front; 598 /// returns the iterator after the last minimal-value element. 599 template<typename Iter, typename Compare> 600 Iter sort_mins( Iter begin, Iter end, Compare& lt ) { 601 if ( begin == end ) return end; 602 603 Iter min_pos = begin; 604 for ( Iter i = begin + 1; i != end; ++i ) { 605 if ( lt( *i, *min_pos ) ) { 606 // new minimum cost; swap into first position 607 min_pos = begin; 608 std::iter_swap( min_pos, i ); 609 } else if ( ! lt( *min_pos, *i ) ) { 610 // duplicate minimum cost; swap into next minimum position 611 ++min_pos; 612 std::iter_swap( min_pos, i ); 613 } 614 } 615 return ++min_pos; 616 } 617 618 template<typename Iter, typename Compare> 619 inline Iter sort_mins( Iter begin, Iter end, Compare&& lt ) { 620 return sort_mins( begin, end, lt ); 621 } 622 623 /// sort_mins defaulted to use std::less 624 template<typename Iter> 625 inline Iter sort_mins( Iter begin, Iter end ) { 626 return sort_mins( begin, end, std::less<typename std::iterator_traits<Iter>::value_type>{} ); 627 } 628 253 629 // Local Variables: // 254 630 // tab-width: 4 //
Note:
See TracChangeset
for help on using the changeset viewer.