00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 #ifndef ENUMSTRINGS_H 00011 #define ENUMSTRINGS_H 00012 00013 #include <iostream> 00014 #include <sstream> 00015 #include <string> 00016 #include <algorithm> 00017 #include <iterator> 00018 #include <boost/range.hpp> 00019 00020 00021 template<typename T> 00022 struct enumStrings 00023 { 00024 static char const* data[]; 00025 }; 00026 00027 template<typename T> 00028 struct enumRefHolder 00029 { 00030 T& enumVal; 00031 enumRefHolder(T& enumVal): enumVal(enumVal) {} 00032 }; 00033 00034 template<typename T> 00035 struct enumConstRefHolder 00036 { 00037 T const& enumVal; 00038 enumConstRefHolder(T const& enumVal): enumVal(enumVal) {} 00039 }; 00040 00041 template<typename T> 00042 inline std::ostream& operator<<(std::ostream& str, enumConstRefHolder<T> const& data) 00043 { 00044 //Add check on enumStrings<T>::data size to ensure correspondence with entries in cafeEnumEpics.h 00045 00046 if ( boost::size( enumStrings<T>::data) > (unsigned int) data.enumVal) { 00047 return str << enumStrings<T>::data[data.enumVal]; 00048 } 00049 else { 00050 return str << "ERROR: enumStrings.h reports data.enumVal= " << data.enumVal 00051 << " DOES NOT HAVE A STRING EQUIVALENT!"; 00052 } 00053 } 00054 00055 00056 template<typename T> 00057 inline std::istream& operator>>(std::istream& str, enumRefHolder<T> const& data) 00058 { 00059 std::string value; 00060 str >> value; 00061 00062 // These two can be made easier to read in C++11 00063 // using std::begin() and std::end() 00064 00065 //static auto begin = std::begin(enumStrings<T>::data); 00066 //static auto end = std::end(enumStrings<T>::data); 00067 //auto find = std::find(begin, end, value); 00068 //if (find != end) 00069 00070 if ( std::find( boost::begin(enumStrings<T>::data), boost::end( enumStrings<T>::data), value) != 00071 boost::end( enumStrings<T>::data)) 00072 { 00073 //data.enumVal = static_cast<T>(std::distance(begin, find)); 00074 data.enumVal = static_cast<T>(std::distance(boost::begin(enumStrings<T>::data), 00075 std::find (boost::begin(enumStrings<T>::data), boost::end(enumStrings<T>::data), value ) )); 00076 } 00077 00078 00079 if (data.enumVal > boost::size( enumStrings<T>::data) ) { 00080 00081 std::cout << "ERROR: enumStrings.h reports data.enumVal = " << data.enumVal 00082 << " is out of enum range = " << boost::size( enumStrings<T>::data) << std::endl; 00083 } 00084 00085 return str; 00086 } 00087 00088 00089 template<typename T> 00090 enumConstRefHolder<T> enumToString(T const& e) {return enumConstRefHolder<T>(e);} 00091 00092 template<typename T> 00093 enumRefHolder<T> enumFromString(T& e) {return enumRefHolder<T>(e);} 00094 00095 00096 00097 00098 #endif // ENUMSTRINGS_H