// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder #ifndef UTILILITIES_HPP #define UTILILITIES_HPP #include #include #include #include #include #include #include #include "cbasetypes.hpp" #include "random.hpp" #ifndef __has_builtin #define __has_builtin(x) 0 #endif // Class used to perform time measurement class cScopeTimer { struct sPimpl; //this is to avoid long compilation time std::unique_ptr aPimpl; cScopeTimer(); }; int levenshtein( const std::string &s1, const std::string &s2 ); namespace rathena { namespace util { template bool map_exists( std::map& map, K key ){ return map.find( key ) != map.end(); } /** * Find a key-value pair and return the key value as a reference * @param map: Map to search through * @param key: Key wanted * @return Key value on success or nullptr on failure */ template V* map_find( std::map& map, K key ){ auto it = map.find( key ); if( it != map.end() ){ return &it->second; }else{ return nullptr; } } /** * Find a key-value pair and return the key value as a reference * @param map: Map to search through * @param key: Key wanted * @return Key value on success or nullptr on failure */ template std::shared_ptr map_find( std::map>& map, K key ){ auto it = map.find( key ); if( it != map.end() ){ return it->second; }else{ return nullptr; } } /** * Get a key-value pair and return the key value * @param map: Map to search through * @param key: Key wanted * @param defaultValue: Value returned if key doesn't exist * @return Key value on success or defaultValue on failure */ template V map_get(std::map& map, K key, V defaultValue) { auto it = map.find(key); if (it != map.end()) return it->second; else return defaultValue; } /** * Resize a map. * @param map: Map to resize * @param size: Size to set map to */ template void map_resize(std::map &map, S size) { auto it = map.begin(); std::advance(it, size); map.erase(it, map.end()); } /** * Find a key-value pair and return the key value as a reference * @param map: Unordered Map to search through * @param key: Key wanted * @return Key value on success or nullptr on failure */ template V* umap_find(std::unordered_map& map, K key) { auto it = map.find(key); if (it != map.end()) return &it->second; else return nullptr; } /** * Find a key-value pair and return the key value as a reference * @param map: Unordered Map to search through * @param key: Key wanted * @return Key value on success or nullptr on failure */ template std::shared_ptr umap_find(std::unordered_map>& map, K key) { auto it = map.find(key); if (it != map.end()) return it->second; else return nullptr; } /** * Get a key-value pair and return the key value * @param map: Unordered Map to search through * @param key: Key wanted * @param defaultValue: Value returned if key doesn't exist * @return Key value on success or defaultValue on failure */ template V umap_get(std::unordered_map& map, K key, V defaultValue) { auto it = map.find(key); if (it != map.end()) return it->second; else return defaultValue; } /** * Resize an unordered map. * @param map: Unordered map to resize * @param size: Size to set unordered map to */ template void umap_resize(std::unordered_map &map, S size) { map.erase(std::advance(map.begin(), map.min(size, map.size())), map.end()); } /** * Get a random value from the given unordered map * @param map: Unordered Map to search through * @return A random value by reference */ template V& umap_random( std::unordered_map& map ){ auto it = map.begin(); std::advance( it, rnd_value( 0, map.size() - 1 ) ); return it->second; } /** * Get a random value from the given vector * @param vec: Vector to search through * @return A random value by reference */ template K &vector_random(std::vector &vec) { auto it = vec.begin(); std::advance(it, rnd_value(0, vec.size() - 1)); return *it; } /** * Get an iterator element * @param vec: Vector to search through * @param value: Value wanted * @return Key value iterator on success or vector end iterator on failure */ template typename std::vector::iterator vector_get(std::vector &vec, V key) { return std::find(vec.begin(), vec.end(), key); } /** * Determine if a value exists in the vector * @param vec: Vector to search through * @param value: Value wanted * @return True on success or false on failure */ template bool vector_exists(const std::vector &vec, V value) { auto it = std::find(vec.begin(), vec.end(), value); if (it != vec.end()) return true; else return false; } /** * Erase an index value from a vector * @param vector: Vector to erase value from * @param index: Index value to remove */ template void erase_at(std::vector& vector, size_t index) { if (vector.size() == 1) { vector.clear(); vector.shrink_to_fit(); } else vector.erase(vector.begin() + index); } /** * Determine if a value exists in the vector and then erase it * @param vector: Vector to erase value from * @param value: Value to remove */ template void vector_erase_if_exists(std::vector &vector, V value) { auto it = std::find(vector.begin(), vector.end(), value); if (it != vector.end()) { if (vector.size() == 1) { vector.clear(); vector.shrink_to_fit(); } else vector.erase(it); } } #if __has_builtin( __builtin_add_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 ) template bool safe_addition(T a, T b, T &result) { return __builtin_add_overflow(a, b, &result); } #else template bool safe_addition( T a, T b, T& result ){ bool overflow = false; if( std::numeric_limits::is_signed ){ if( b < 0 ){ if( a < ( (std::numeric_limits::min)() - b ) ){ overflow = true; } }else{ if( a > ( (std::numeric_limits::max)() - b ) ){ overflow = true; } } }else{ if( a > ( (std::numeric_limits::max)() - b ) ){ overflow = true; } } result = a + b; return overflow; } #endif bool safe_substraction( int64 a, int64 b, int64& result ); bool safe_multiplication( int64 a, int64 b, int64& result ); /** * Safely add values without overflowing. * @param a: Holder of value to increment * @param b: Increment by * @param cap: Cap value * @return Result of a + b */ template T safe_addition_cap( T a, T b, T cap ){ T result; if( rathena::util::safe_addition( a, b, result ) ){ return cap; }else{ return result; } } template void tolower( T& string ){ std::transform( string.begin(), string.end(), string.begin(), ::tolower ); } } } #endif /* UTILILITIES_HPP */