/* * utilite is a cross-platform library with * useful utilities for fast and small developing. * Copyright (C) 2010 Mathieu Labbe * * utilite is free library: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * utilite is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef USTL_H #define USTL_H #include #include #include #include #include #include #include /** * \file UStl.h * \brief Wrappers of STL for convenient functions. * * All functions you will find here are here * for the use of STL in a more convenient way. */ /** * Get unique keys from a std::multimap. * @param mm the multimap * @return the list which contains unique keys */ template inline std::list uUniqueKeys(const std::multimap & mm) { std::list l; typename std::list::reverse_iterator lastValue; for(typename std::multimap::const_iterator iter = mm.begin(); iter!=mm.end(); ++iter) { if(iter == mm.begin() || (iter != mm.begin() && *lastValue != iter->first)) { l.push_back(iter->first); lastValue = l.rbegin(); } } return l; } /** * Get all keys from a std::multimap. * @param mm the multimap * @return the vector which contains all keys (may contains duplicated keys) */ template inline std::vector uKeys(const std::multimap & mm) { std::vector v(mm.size()); int i=0; for(typename std::multimap::const_iterator iter = mm.begin(); iter!=mm.end(); ++iter) { v[i++] = iter->first; } return v; } /** * Get all keys from a std::multimap. * @param mm the multimap * @return the list which contains all keys (may contains duplicated keys) */ template inline std::list uKeysList(const std::multimap & mm) { std::list l; for(typename std::multimap::const_iterator iter = mm.begin(); iter!=mm.end(); ++iter) { l.push_back(iter->first); } return l; } /** * Get all values from a std::multimap. * @param mm the multimap * @return the vector which contains all values (contains values from duplicated keys) */ template inline std::vector uValues(const std::multimap & mm) { std::vector v(mm.size()); int i=0; for(typename std::multimap::const_iterator iter = mm.begin(); iter!=mm.end(); ++iter) { v[i++] = iter->second; } return v; } /** * Get all values from a std::multimap. * @param mm the multimap * @return the list which contains all values (contains values from duplicated keys) */ template inline std::list uValuesList(const std::multimap & mm) { std::list l; for(typename std::multimap::const_iterator iter = mm.begin(); iter!=mm.end(); ++iter) { l.push_back(iter->second); } return l; } /** * Get values for a specified key from a std::multimap. * @param mm the multimap * @param key the key * @return the list which contains the values of the key */ template inline std::list uValues(const std::multimap & mm, const K & key) { std::list l; std::pair::const_iterator, typename std::multimap::const_iterator> range; range = mm.equal_range(key); for(typename std::multimap::const_iterator iter = range.first; iter!=range.second; ++iter) { l.push_back(iter->second); } return l; } /** * Get all keys from a std::map. * @param m the map * @return the vector of keys */ template inline std::vector uKeys(const std::map & m) { std::vector v(m.size()); int i=0; for(typename std::map::const_iterator iter = m.begin(); iter!=m.end(); ++iter) { v[i] = iter->first; ++i; } return v; } /** * Get all keys from a std::map. * @param m the map * @return the list of keys */ template inline std::list uKeysList(const std::map & m) { std::list l; for(typename std::map::const_iterator iter = m.begin(); iter!=m.end(); ++iter) { l.push_back(iter->first); } return l; } /** * Get all keys from a std::map. * @param m the map * @return the set of keys */ template inline std::set uKeysSet(const std::map & m) { std::set s; int i=0; for(typename std::map::const_iterator iter = m.begin(); iter!=m.end(); ++iter) { s.insert(s.end(), iter->first); ++i; } return s; } /** * Get all values from a std::map. * @param m the map * @return the vector of values */ template inline std::vector uValues(const std::map & m) { std::vector v(m.size()); int i=0; for(typename std::map::const_iterator iter = m.begin(); iter!=m.end(); ++iter) { v[i] = iter->second; ++i; } return v; } /** * Get all values from a std::map. * @param m the map * @return the list of values */ template inline std::list uValuesList(const std::map & m) { std::list l; for(typename std::map::const_iterator iter = m.begin(); iter!=m.end(); ++iter) { l.push_back(iter->second); } return l; } /** * Get the value of a specified key from a std::map. * @param m the map * @param key the key * @param defaultValue the default value used if the key is not found * @return the value */ template inline V uValue(const std::map & m, const K & key, const V & defaultValue = V()) { V v = defaultValue; typename std::map::const_iterator i = m.find(key); if(i != m.end()) { v = i->second; } return v; } /** * Get the value of a specified key from a std::map. This will * remove the value from the map; * @param m the map * @param key the key * @param defaultValue the default value used if the key is not found * @return the value */ template inline V uTake(std::map & m, const K & key, const V & defaultValue = V()) { V v; typename std::map::iterator i = m.find(key); if(i != m.end()) { v = i->second; m.erase(i); } else { v = defaultValue; } return v; } /** * Get the iterator at a specified position in a std::list. If the position * is out of range, the result is the end iterator of the list. * @param list the list * @param pos the index position in the list * @return the iterator at the specified index */ template inline typename std::list::iterator uIteratorAt(std::list & list, const unsigned int & pos) { typename std::list::iterator iter = list.begin(); for(unsigned int i = 0; i inline typename std::list::const_iterator uIteratorAt(const std::list & list, const unsigned int & pos) { typename std::list::const_iterator iter = list.begin(); for(unsigned int i = 0; i inline typename std::set::iterator uIteratorAt(std::set & set, const unsigned int & pos) { typename std::set::iterator iter = set.begin(); for(unsigned int i = 0; i inline typename std::set::const_iterator uIteratorAt(const std::set & set, const unsigned int & pos) { typename std::set::const_iterator iter = set.begin(); for(unsigned int i = 0; i inline typename std::vector::iterator uIteratorAt(std::vector & v, const unsigned int & pos) { return v.begin() + pos; } /** * Get the iterator at a specified position in a std::vector. If the position * is out of range, the result is the end iterator of the vector. * @param v the vector * @param pos the index position in the vector * @return the iterator at the specified index */ template inline typename std::vector::const_iterator uIteratorAt(const std::vector & v, const unsigned int & pos) { return v.begin() + pos; } /** * Get the value at a specified position in a std::list. If the position * is out of range, the result is undefined. * @param list the list * @param pos the index position in the list * @return the value at the specified index */ template inline V & uValueAt(std::list & list, const unsigned int & pos) { typename std::list::iterator iter = uIteratorAt(list, pos); return *iter; } /** * Get the value at a specified position in a std::list. If the position * is out of range, the result is undefined. * @param list the list * @param pos the index position in the list * @return the value at the specified index */ template inline const V & uValueAt(const std::list & list, const unsigned int & pos) { typename std::list::const_iterator iter = uIteratorAt(list, pos); return *iter; } /** * Check if the list contains the specified value. * @param list the list * @param value the value * @return true if the value is found in the list, otherwise false */ template inline bool uContains(const std::list & list, const V & value) { return std::find(list.begin(), list.end(), value) != list.end(); } /** * Check if the map contains the specified key. * @param map the map * @param key the key * @return true if the value is found in the map, otherwise false */ template inline bool uContains(const std::map & map, const K & key) { return map.find(key) != map.end(); } /** * Check if the multimap contains the specified key. * @param map the map * @param key the key * @return true if the value is found in the map, otherwise false */ template inline bool uContains(const std::multimap & map, const K & key) { return map.find(key) != map.end(); } /** * Insert an item in the map. Contrary to the insert in the STL, * if the key already exists, the value will be replaced by the new one. */ template inline void uInsert(std::map & map, const std::pair & pair) { std::pair::iterator, bool> inserted = map.insert(pair); if(inserted.second == false) { inserted.first->second = pair.second; } } /** * Insert items in the map. Contrary to the insert in the STL, * if the key already exists, the value will be replaced by the new one. */ template inline void uInsert(std::map & map, const std::map & items) { for(typename std::map::const_iterator iter=items.begin(); iter!=items.end(); ++iter) { std::pair::iterator, bool> inserted = map.insert(*iter); if(inserted.second == false) { inserted.first->second = iter->second; } } } /** * Convert a std::list to a std::vector. * @param list the list * @return the vector */ template inline std::vector uListToVector(const std::list & list) { return std::vector(list.begin(), list.end()); } /** * Convert a std::vector to a std::list. * @param v the vector * @return the list */ template inline std::list uVectorToList(const std::vector & v) { return std::list(v.begin(), v.end()); } /** * Convert a std::multimap to a std::map * @see uMultimapToMapUnique to keep only unique keys */ template inline std::map uMultimapToMap(const std::multimap & m) { return std::map(m.begin(), m.end()); } /** * Convert a std::multimap to a std::map, keeping only unique keys! */ template inline std::map uMultimapToMapUnique(const std::multimap & m) { std::map mapOut; std::list uniqueKeys = uUniqueKeys(m); for(typename std::list::const_iterator iter = uniqueKeys.begin(); iter!=uniqueKeys.end(); ++iter) { if(m.count(*iter) == 1) { typename std::multimap::const_iterator jter=m.find(*iter); mapOut.insert(mapOut.end(), std::pair(jter->first, jter->second)); } } return mapOut; } /** * Append a list to another list. * @param list the list on which the other list will be appended * @param newItems the list of items to be appended */ template inline void uAppend(std::list & list, const std::list & newItems) { list.insert(list.end(), newItems.begin(), newItems.end()); } /** * Get the index in the list of the specified value. S negative index is returned * if the value is not found. * @param list the list * @param value the value * @return the index of the value in the list */ template inline int uIndexOf(const std::vector & list, const V & value) { int index=-1; int i=0; for(typename std::vector::const_iterator iter = list.begin(); iter!=list.end(); ++iter) { if(*iter == value) { index = i; break; } ++i; } return index; } /** * Split a string into multiple string around the specified separator. * Example: * @code * std::list v = split("Hello the world!", ' '); * @endcode * The list v will contain {"Hello", "the", "world!"} * @param str the string * @param separator the separator character * @return the list of strings */ inline std::list uSplit(const std::string & str, char separator = ' ') { std::list v; std::string buf; for(unsigned int i=0; i v; * v.push_back("Hello"); * v.push_back("world!"); * std::string joined = split(v, " "); * @endcode * The output string is "Hello world!" * @param strings a list of strings * @param separator the separator string * @return the joined string */ inline std::string uJoin(const std::list & strings, const std::string & separator = "") { std::string out; for(std::list::const_iterator iter = strings.begin(); iter!=strings.end(); ++iter) { if(iter!=strings.begin() && !separator.empty()) { out += separator; } out+=*iter; } return out; } /** * Check if a character is a digit. * @param c the character * @return true if the character is a digit (if c >= '0' && c <= '9') */ inline bool uIsDigit(const char c) { return c >= '0' && c <= '9'; } /** * Check if a string is a integer number. * @param str the string * @return true if the string is a integer number */ inline bool uIsInteger(const std::string & str, bool checkForSign = true) { bool isInteger = str.size()!=0; for(unsigned int i=0; i list = uSplit(str, '.'); if(list.size() == 1) { return uIsInteger(str); } else if(list.size() == 2) { return uIsInteger(list.front()) && uIsInteger(list.back(), false); } return false; } /** * Split a string into number and character strings. * Example: * @code * std::list v = uSplit("Hello 03 my 65 world!"); * @endcode * The list v will contain {"Hello ", "03", " my ", "65", " world!"} * @param str the string * @return the list of strings */ inline std::list uSplitNumChar(const std::string & str) { std::list list; std::string buf; bool num = false; for(unsigned int i=0; ib */ inline int uStrNumCmp(const std::string & a, const std::string & b) { std::vector listA; std::vector listB; listA = uListToVector(uSplitNumChar(a)); listB = uListToVector(uSplitNumChar(b)); unsigned int i; int result = 0; for(i=0; i listA[i].size()) { result = -1; } else { result = listA[i].compare(listB[i]); } } else if(uIsDigit(listA[i].at(0))) { result = -1; } else if(uIsDigit(listB[i].at(0))) { result = 1; } else { result = listA[i].compare(listB[i]); } if(result != 0) { break; } } return result; } /** * Check if a string contains a specified substring. */ inline bool uStrContains(const std::string & string, const std::string & substring) { return string.find(substring) != std::string::npos; } inline int uCompareVersion(const std::string & version, int major, int minor=-1, int patch=-1) { std::vector v = uListToVector(uSplit(version, '.')); if(v.size() == 3) { int vMajor = atoi(v[0].c_str()); int vMinor = atoi(v[1].c_str()); int vPatch = atoi(v[2].c_str()); if(vMajor > major || (vMajor == major && minor!=-1 && vMinor > minor) || (vMajor == major && minor!=-1 && vMinor == minor && patch!=-1 && vPatch > patch)) { return 1; } else if(vMajor == major && (minor == -1 || (vMinor == minor && (patch == -1 || vPatch == patch)))) { return 0; } } return -1; } #endif /* USTL_H */