The Sparta Modeling Framework
Loading...
Searching...
No Matches
Utils.hpp
1// <Utils> -*- C++ -*-
2
3#pragma once
4
5#include <string>
6#include <math.h>
7#include <cxxabi.h>
8#include <vector>
9#include <algorithm>
10
11#include <boost/uuid/uuid.hpp>
12#include <boost/uuid/uuid_generators.hpp>
13#include <boost/uuid/uuid_io.hpp>
14
17#include "sparta/utils/SpartaExpBackoff.hpp"
18
20#define NULL_TO_EMPTY_STR(s) (((s)==nullptr)?"":s)
21
26#define DEMANGLE_BUF_LENGTH 4096
27
28
29// Custom Literals
30
34constexpr inline uint64_t operator ""_u64(unsigned long long i) {
35 return i;
36}
37
41constexpr inline uint32_t operator ""_u32(unsigned long long i) {
42 return i;
43}
44
48constexpr inline uint16_t operator ""_u16(unsigned long long i) {
49 return i;
50}
51
55constexpr inline uint8_t operator ""_u8(unsigned long long i) {
56 return i;
57}
58
62constexpr inline int64_t operator ""_64(unsigned long long i) {
63 return i;
64}
65
69constexpr inline int32_t operator ""_32(unsigned long long i) {
70 return i;
71}
72
76constexpr inline int16_t operator ""_16(unsigned long long i) {
77 return i;
78}
79
83constexpr inline int8_t operator ""_8(unsigned long long i) {
84 return i;
85}
86
87namespace sparta
88{
89
90inline std::string generateUUID()
91{
92 boost::uuids::uuid uuid = boost::uuids::random_generator()();
93 std::string uuid_str = boost::uuids::to_string(uuid);
94 return uuid_str;
95}
96
103template<typename K, typename V, typename... Args, template<typename...> class MapType>
104MapType<V, K> flipMap(const MapType<K, V, Args...>& map){
105 auto inverted_map {MapType<V, K>{}};
106 for(const auto& [key, value] : map){
107 inverted_map.insert({value, key});
108 }
109 return inverted_map;
110}
111
134template <typename T,
135 typename ConstT=typename std::add_pointer<
136 typename std::add_const<
137 typename std::remove_pointer<T>::type
138 >::type
139 >::type>
141 typedef ConstT type;
142};
143
153inline bool isPowerOf2(uint64_t x) {
154 return ((x==0) || !(x & (x-1)));
155}
156
170template <typename T>
171inline T computeMask(T size, T& lsb_pos) {
172 T mask;
173 if(size >= 1){
174 double tmp = log2(size);
175 if(tmp != floor(tmp)){
176 throw SpartaException("For computeMask, size must be a power of 2, is ")
177 << size;
178 }
179 lsb_pos = (T)tmp;
180 mask = ~((1 << lsb_pos) - 1);
181
182 sparta_assert((1ul << lsb_pos) == size);
183 }else{
184 lsb_pos = sizeof(T) * 8;
185 mask = (T)0;
186 }
187 return mask;
188}
189
197template <typename T>
198inline T computeMaskShift(T size) {
199 T shift;
200 computeMask(size, shift);
201 return shift;
202}
203
204
214inline std::string demangle(const std::string& name) noexcept {
215 char buf[DEMANGLE_BUF_LENGTH];
216 size_t buf_size = DEMANGLE_BUF_LENGTH;
217 int status;
218 char* out = __cxxabiv1::__cxa_demangle(name.c_str(), buf, &buf_size, &status);
219 if(nullptr == out){
220 return name;
221 }
222 return std::string(out);
223}
224
234template <typename T>
235inline T* notNull(T* p) {
236 if(p == nullptr){
237 throw SpartaException("notNull: pointer was null: " + demangle(typeid(T).name()));
238 }
239 return p;
240}
241
247template <typename T> struct is_vector {
253 static const bool value = false;
254};
255
257template <typename T> struct is_vector<std::vector<T> > {
258 static const bool value = true;
259};
260
276inline uint32_t replaceSubstring(std::string& s, const std::string& from, const std::string& to){
277 uint32_t num_replacements = 0;
278 size_t pos = 0;
279 while((pos = s.find(from, pos)) != std::string::npos) {
280 s.replace(pos, from.size(), to);
281 pos += to.length();
282 ++num_replacements;
283 }
284 return num_replacements;
285}
286
293inline std::string copyWithReplace(const std::string& s, char from, const std::string& to){
294 std::string result;
295 result.reserve(s.size()*2); // Take an initial guess so we don't have to reallocate
296
297 const char* p = s.c_str();
298 while(1){
299 if(*p == from){
300 result += to;
301 }else if(*p == '\0'){
302 break;
303 }else{
304 result += *p;
305 }
306 ++p;
307 }
308
309 return result;
310}
311
318inline std::string convertCPPStringToPython(const std::string& s)
319{
320 std::string result = s;
321 const char * cpp_stuff = "<>:";
322 const char replacement = '_';
323
324 std::string::size_type pos;
325 while(pos = result.find_first_of(cpp_stuff), pos != std::string::npos) {
326 result[pos] = replacement;
327 }
328
329 // Strip parens
330 while(pos = result.find_first_of("()"), pos != std::string::npos) {
331 std::string newstr = result.substr(0, pos);
332 newstr += result.substr(pos + 1);
333 result = newstr;
334 }
335
336
337 return result;
338}
339
343inline void writeNChars(std::ostream& out, uint32_t num, char chr=' ') {
344 for(uint32_t i=0; i<num; ++i){
345 out << chr;
346 }
347}
348
352inline std::string toLower(const std::string& s){
353 std::string out(s.size(), ' ');
354 std::transform(s.begin(), s.end(), out.begin(), (int(*)(int))std::tolower);
355 return out;
356}
357
364template <bool Default>
366{
367 bool value_ = Default;
368
369public:
370
374 OneWayBool() = default;
375
376 /*
377 * \brief Initialize with a value. This value must be the opposite of value
378 */
379 OneWayBool(bool value)
380 : value_(value)
381 {
382 sparta_assert(value != Default,
383 "OneWayBool<" << Default << "> can only be explicitly initalized to " << !Default
384 << ". Otherwise, it must be default-constructed which will provide a value of "
385 << Default);
386 }
387
391 operator bool () const { return value_; }
392
396 bool operator==(bool b) const { return value_ == b; }
397
401 template <bool ArgDefault>
402 bool operator==(const OneWayBool<ArgDefault>& b) const { return value_ == b.value_; }
403
409 template <bool ArgDefault>
411 sparta_assert(Default != b.value_,
412 "OneWayBool<" << Default << "> can never be set to " << Default
413 << " except at initialization");
414 value_ = b.value;
415 return value_;
416 }
417
423 bool operator=(bool b) {
424 sparta_assert(Default != b,
425 "OneWayBool<" << Default << "> can never be set to " << Default
426 << " except at initialization");
427 value_ = b;
428 return value_;
429 }
430
437 void set_DEPRECATED(bool b) {
438 value_ = b;
439 }
440};
441
447template <typename T>
449{
450 OneWayBool<false> set_;
451
452 bool defaulted_ = false;
453
454 T value_;
455
456 const char * name_ = nullptr;
457
458public:
459
464 : set_(rhp.set_),
465 defaulted_(rhp.defaulted_),
466 value_(rhp.value_),
467 name_(rhp.name_)
468 {;}
469
474 : set_(rhp.set_),
475 defaulted_(rhp.defaulted_),
476 value_(rhp.value_),
477 name_(rhp.name_)
478 {
479 // No need to invalidate rhp
480 }
481
489 AssignOnceObject(const T& def_value,
490 const char* name)
491 : defaulted_(true),
492 value_(def_value),
493 name_(name)
494 {;}
495
501
505 operator const T& () const {
506 return get();
507 }
508
512 const T& get() const {
513 sparta_assert(set_ || defaulted_, getPrintableQuotedName_() << " must be set before reading");
514 return value_;
515 }
516
520 bool operator==(const AssignOnceObject<T>& b) const {
521 sparta_assert(set_ || defaulted_, getPrintableQuotedName_() << " must be set before comparing");
522 return value_ == b.get();
523 }
524
528 const T& operator=(const AssignOnceObject<T>& b) {
529 sparta_assert(set_ == false,
530 getPrintableQuotedName_() << " has already been assigned once. It cannot be re-assigned");
531 sparta_assert(b.set_ || b.defaulted_,
532 getPrintableQuotedName_() << " cannot be assigned with another AssignOnceObject which is not defaulted or set");
533
534 set_ = true; // arg 'b' must be defaulted or set
535 value_ = b.value_;
536 return value_;
537 }
538
542 const T& operator=(const T& v) {
543 sparta_assert(set_ == false,
544 getPrintableQuotedName_() << " has already been assigned once. It cannot be re-assigned");
545
546 set_ = true;
547 value_ = v;
548 return value_;
549 }
550
551 /*
552 * \brief Has this value been assigned
553 */
554 bool assigned() const {
555 return set_;
556 }
557
558private:
559
560 template <typename X>
561 friend inline std::ostream& operator<<(std::ostream& o, const AssignOnceObject<X>& v);
562
568 std::string getPrintableQuotedName_() const {
569 if(name_ != nullptr){
570 return std::string("\"") + name_ + "\"";
571 }else{
572 return std::string("\"AssignOnceObject<") + typeid(T).name() + ">";
573 }
574 }
575};
576
577template <typename T>
578inline std::ostream& operator<<(std::ostream& o, const AssignOnceObject<T>& v) {
579 if(v.set_ || v.defaulted_){
580 o << v.value_;
581 }else{
582 o << "<uninitialized>";
583 }
584 return o;
585}
586
593template <typename T, T min_bound=std::numeric_limits<T>::min(), T max_bound=std::numeric_limits<T>::max()>
595{
596 T val_;
597public:
598
599 bounded_int(const bounded_int&) = default;
600
601 explicit bounded_int(bounded_int&&) = default;
602
603 template <typename ArgT=T>
604 bounded_int(ArgT, typename std::enable_if<std::is_integral<ArgT>::value==false
605 && std::is_convertible<ArgT,T>::value==false>::type* = 0)
606 : val_(0)
607 {
608 static_assert(std::is_integral<ArgT>::value,
609 "Cannot store a non-integral value in a bounded integer type");
610 }
611
612 template <typename ArgT=T>
613 bounded_int(ArgT val, typename std::enable_if<std::is_integral<ArgT>::value==false
614 && std::is_convertible<ArgT,T>::value==true>::type* = 0)
615 : val_(static_cast<T>(val))
616 {
617 rangeCheck_(static_cast<T>(val));
618 }
619
620 // Different sign
621 template <typename ArgT=T>
622 bounded_int(ArgT val, typename std::enable_if<std::is_integral<ArgT>::value
623 && std::is_signed<ArgT>::value!=std::is_signed<T>::value>::type* = 0)
624 : val_(val)
625 {
626 rangeCheck_(val);
627 }
628
629 // Same sign, smaller (or same-sized) input value data type
630 template <typename ArgT=T>
631 bounded_int(ArgT val, typename std::enable_if<std::is_integral<ArgT>::value
632 && (sizeof(ArgT) <= sizeof(T))
633 && std::is_signed<ArgT>::value==std::is_signed<T>::value>::type* = 0)
634 : val_(val)
635 {
636 // Types have same signed-ness and argument is smaller than container.
637 // Container type T bounds guaranteed unexceeded
638
639 // Check bounds if there are user defined bounds
640
641 rangeCheck_(val);
642 }
643
644 // Same sign, larger input value data type
645 template <typename ArgT=T>
646 bounded_int(ArgT val, typename std::enable_if<std::is_integral<ArgT>::value
647 && (sizeof(ArgT) > sizeof(T))
648 && std::is_signed<ArgT>::value==std::is_signed<T>::value>::type* = 0)
649 : val_(val)
650 {
651 // Types have same signed-ness but argument is larger
652 rangeCheck_(val);
653 }
654
655 template <typename ArgT>
656 void rangeCheck_(ArgT val){
657 lowerRangeCheck_(val);
658 upperRangeCheck_(val);
659 }
660
661 template <typename ArgT=T>
662 typename std::enable_if<std::numeric_limits<ArgT>::min()!=min_bound, void>::type
663 lowerRangeCheck_(ArgT val) const {
664 sparta_assert(val >= min_bound,
665 "Tried to store a " << typeid(ArgT).name() << " into a bounded " << typeid(T).name() << ". Not safe to "
666 "cast " << val << " into a type with a minimum of " << min_bound);
667 }
668
669 template <typename ArgT=T>
670 typename std::enable_if<std::numeric_limits<ArgT>::min()==min_bound, void>::type
671 lowerRangeCheck_(ArgT val) const {
672 (void) val; // Lower bound of val is same as this bounded_int
673 }
674
675 template <typename ArgT=T>
676 typename std::enable_if<std::numeric_limits<ArgT>::max()!=max_bound, void>::type
677 upperRangeCheck_(ArgT val) const {
678 sparta_assert(val <= max_bound,
679 "Tried to store a " << typeid(ArgT).name() << " into a bounded " << typeid(T).name() << ". Not safe to "
680 "cast " << val << " into a type with a maximum of " << max_bound);
681 }
682
683 template <typename ArgT=T>
684 typename std::enable_if<std::numeric_limits<ArgT>::max()==max_bound, void>::type
685 upperRangeCheck_(ArgT val) const {
686 (void) val; // Upper bound of val is same as this bounded_int
687 }
688
693 //template <T local_min_bound, T local_max_bound, typename U=T>
694 //static T bound(U value) {
695 // bt = bounded_type<T, local_min_bound, local_max_bound>(value);
696 // return bt.val_;
697 //}
698
703 operator T() const { return val_; }
704
708 bool operator==(const bounded_int&) = delete;
709
713 bool operator=(const bounded_int&) = delete;
714
715};
716
717} // namespace sparta
718
735#define GENERATE_HAS_ATTR(name) \
736 template <typename T> \
737 struct has_attr_##name { \
738 typedef char one[1]; \
739 typedef char two[2]; \
740 \
741 template <typename C> static one& test( decltype(&C::name) ) ; \
742 template <typename C> static two& test(...); \
743 \
744 enum { value = sizeof(test<T>(nullptr)) == sizeof(one) }; \
745 };
Set of macros for Sparta assertions. Caught by the framework.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
Exception class for all of Sparta.
Object which can only have it's value set once. Throws exception if being set more than once.
Definition Utils.hpp:449
const T & operator=(const T &v)
Assign using a given value of type T.
Definition Utils.hpp:542
AssignOnceObject()
Construct with no name.
Definition Utils.hpp:499
AssignOnceObject(const AssignOnceObject &rhp)
Copy Constructor.
Definition Utils.hpp:463
const T & operator=(const AssignOnceObject< T > &b)
Assign using another AssignOnceObject of the same contained type T.
Definition Utils.hpp:528
const T & get() const
Get contained value of type T.
Definition Utils.hpp:512
AssignOnceObject(AssignOnceObject &&rhp)
Move-Construction disabled until needed.
Definition Utils.hpp:473
AssignOnceObject(const T &def_value, const char *name)
Construct with a default and name for use during errors. This constructor starts the object in unassi...
Definition Utils.hpp:489
bool operator==(const AssignOnceObject< T > &b) const
Compare against another AssignOnceObject of the same contained type T.
Definition Utils.hpp:520
Boolean with a default capable of being changed to the opposite value only. it can never set to the d...
Definition Utils.hpp:366
OneWayBool()=default
Default construction. Defaults to template argument 'Default'.
bool operator=(bool b)
Assign value from a bool.
Definition Utils.hpp:423
bool operator=(const OneWayBool< ArgDefault > &b)
Assign value from another OneWayBool.
Definition Utils.hpp:410
bool operator==(const OneWayBool< ArgDefault > &b) const
Compare value with another OneWayBool.
Definition Utils.hpp:402
void set_DEPRECATED(bool b)
set this object arbitrarily
Definition Utils.hpp:437
bool operator==(bool b) const
Compare value with a bool.
Definition Utils.hpp:396
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Bounded integer type with range-checking.
Definition Utils.hpp:595
bool operator=(const bounded_int &)=delete
Deleted comaprison with bounded in (until implemented fully)
bool operator==(const bounded_int &)=delete
Deleted comaprison with bounded in (until implemented fully)
Macros for handling exponential backoff.
std::string convertCPPStringToPython(const std::string &s)
Take all of the C++-isms out of a string (like parens, angle brackets, colons, etc) and replace them ...
Definition Utils.hpp:318
std::string copyWithReplace(const std::string &s, char from, const std::string &to)
Copies from 1 string to another with replacement of a single character with a string.
Definition Utils.hpp:293
T * notNull(T *p)
Ensures that a pointer is not null.
Definition Utils.hpp:235
void writeNChars(std::ostream &out, uint32_t num, char chr=' ')
Insert a number of some character into an ostream.
Definition Utils.hpp:343
uint32_t replaceSubstring(std::string &s, const std::string &from, const std::string &to)
Replaces within a string 's' all instances of some string 'from' with 'to'.
Definition Utils.hpp:276
std::ostream & operator<<(std::ostream &o, const SimulationInfo &info)
ostream insertion operator for SimulationInfo
std::string demangle(const std::string &name) noexcept
Demangles a C++ symbol.
Definition Utils.hpp:214
T computeMask(T size, T &lsb_pos)
Computes a maks and the lsb-position given a block size. The mask generated can be AND-ed with any nu...
Definition Utils.hpp:171
MapType< V, K > flipMap(const MapType< K, V, Args... > &map)
Function to invert a maps or an unordered_map, or any type of class that has key/value semantics....
Definition Utils.hpp:104
std::string toLower(const std::string &s)
Makes a copy of an input string s in lower-case.
Definition Utils.hpp:352
T computeMaskShift(T size)
Convenience wrapper around computeMask to get the shift value.
Definition Utils.hpp:198
bool isPowerOf2(uint64_t x)
Determines if input is 0 or a power of 2.
Definition Utils.hpp:153
Templated for determining if ValueType is std::vector for use in metaprogramming constructs....
Definition Utils.hpp:247
static const bool value
'value' field used by enable_if construct.
Definition Utils.hpp:253
Template type helper that removes a pointer, adds a const, and then re-adds the pointer....
Definition Utils.hpp:140