utilities.hpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. // Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #ifndef UTILILITIES_HPP
  4. #define UTILILITIES_HPP
  5. #include <algorithm>
  6. #include <locale>
  7. #include <map>
  8. #include <memory>
  9. #include <string>
  10. #include <unordered_map>
  11. #include <vector>
  12. #include "cbasetypes.hpp"
  13. #include "random.hpp"
  14. #ifndef __has_builtin
  15. #define __has_builtin(x) 0
  16. #endif
  17. // Class used to perform time measurement
  18. class cScopeTimer {
  19. struct sPimpl; //this is to avoid long compilation time
  20. std::unique_ptr<sPimpl> aPimpl;
  21. cScopeTimer();
  22. };
  23. int levenshtein( const std::string &s1, const std::string &s2 );
  24. namespace rathena {
  25. namespace util {
  26. template <typename K, typename V> bool map_exists( std::map<K,V>& map, K key ){
  27. return map.find( key ) != map.end();
  28. }
  29. /**
  30. * Find a key-value pair and return the key value as a reference
  31. * @param map: Map to search through
  32. * @param key: Key wanted
  33. * @return Key value on success or nullptr on failure
  34. */
  35. template <typename K, typename V> V* map_find( std::map<K,V>& map, K key ){
  36. auto it = map.find( key );
  37. if( it != map.end() ){
  38. return &it->second;
  39. }else{
  40. return nullptr;
  41. }
  42. }
  43. /**
  44. * Find a key-value pair and return the key value as a reference
  45. * @param map: Map to search through
  46. * @param key: Key wanted
  47. * @return Key value on success or nullptr on failure
  48. */
  49. template <typename K, typename V> std::shared_ptr<V> map_find( std::map<K,std::shared_ptr<V>>& map, K key ){
  50. auto it = map.find( key );
  51. if( it != map.end() ){
  52. return it->second;
  53. }else{
  54. return nullptr;
  55. }
  56. }
  57. /**
  58. * Get a key-value pair and return the key value
  59. * @param map: Map to search through
  60. * @param key: Key wanted
  61. * @param defaultValue: Value returned if key doesn't exist
  62. * @return Key value on success or defaultValue on failure
  63. */
  64. template <typename K, typename V> V map_get(std::map<K, V>& map, K key, V defaultValue) {
  65. auto it = map.find(key);
  66. if (it != map.end())
  67. return it->second;
  68. else
  69. return defaultValue;
  70. }
  71. /**
  72. * Resize a map.
  73. * @param map: Map to resize
  74. * @param size: Size to set map to
  75. */
  76. template <typename K, typename V, typename S> void map_resize(std::map<K, V> &map, S size) {
  77. auto it = map.begin();
  78. std::advance(it, size);
  79. map.erase(it, map.end());
  80. }
  81. /**
  82. * Determine if a value exists in the unordered_map
  83. * @param map: Unordered Map to search through
  84. * @param key: Key wanted
  85. * @return True on success or false on failure
  86. */
  87. template <typename K, typename V> bool umap_exists(std::unordered_map<K, V> &map, K key) {
  88. return map.find(key) != map.end();
  89. }
  90. /**
  91. * Find a key-value pair and return the key value as a reference
  92. * @param map: Unordered Map to search through
  93. * @param key: Key wanted
  94. * @return Key value on success or nullptr on failure
  95. */
  96. template <typename K, typename V> V* umap_find(std::unordered_map<K, V>& map, K key) {
  97. auto it = map.find(key);
  98. if (it != map.end())
  99. return &it->second;
  100. else
  101. return nullptr;
  102. }
  103. /**
  104. * Find a key-value pair and return the key value as a reference
  105. * @param map: Unordered Map to search through
  106. * @param key: Key wanted
  107. * @return Key value on success or nullptr on failure
  108. */
  109. template <typename K, typename V> std::shared_ptr<V> umap_find(std::unordered_map<K, std::shared_ptr<V>>& map, K key) {
  110. auto it = map.find(key);
  111. if (it != map.end())
  112. return it->second;
  113. else
  114. return nullptr;
  115. }
  116. /**
  117. * Get a key-value pair and return the key value
  118. * @param map: Unordered Map to search through
  119. * @param key: Key wanted
  120. * @param defaultValue: Value returned if key doesn't exist
  121. * @return Key value on success or defaultValue on failure
  122. */
  123. template <typename K, typename V> V umap_get(std::unordered_map<K, V>& map, K key, V defaultValue) {
  124. auto it = map.find(key);
  125. if (it != map.end())
  126. return it->second;
  127. else
  128. return defaultValue;
  129. }
  130. /**
  131. * Resize an unordered map.
  132. * @param map: Unordered map to resize
  133. * @param size: Size to set unordered map to
  134. */
  135. template <typename K, typename V, typename S> void umap_resize(std::unordered_map<K, V> &map, S size) {
  136. map.erase(std::advance(map.begin(), map.min(size, map.size())), map.end());
  137. }
  138. /**
  139. * Get a random value from the given unordered map
  140. * @param map: Unordered Map to search through
  141. * @return A random value by reference
  142. */
  143. template <typename K, typename V> V& umap_random( std::unordered_map<K, V>& map ){
  144. auto it = map.begin();
  145. std::advance( it, rnd_value<size_t>( 0, map.size() - 1 ) );
  146. return it->second;
  147. }
  148. /**
  149. * Determine if a value exists in the multimap
  150. * @param map: Multimap to search through
  151. * @param key: Key wanted
  152. * @return True on success or false on failure
  153. */
  154. template <typename K, typename V> bool mmap_exists(std::multimap<K, V> &map, K key) {
  155. return map.find(key) != map.end();
  156. }
  157. /**
  158. * Get a random value from the given vector
  159. * @param vec: Vector to search through
  160. * @return A random value by reference
  161. */
  162. template <typename K> K &vector_random(std::vector<K> &vec) {
  163. auto it = vec.begin();
  164. std::advance( it, rnd_value<size_t>( 0, vec.size() - 1 ) );
  165. return *it;
  166. }
  167. /**
  168. * Get an iterator element
  169. * @param vec: Vector to search through
  170. * @param value: Value wanted
  171. * @return Key value iterator on success or vector end iterator on failure
  172. */
  173. template <typename K, typename V> typename std::vector<K>::iterator vector_get(std::vector<K> &vec, V key) {
  174. return std::find(vec.begin(), vec.end(), key);
  175. }
  176. /**
  177. * Determine if a value exists in the vector
  178. * @param vec: Vector to search through
  179. * @param value: Value wanted
  180. * @return True on success or false on failure
  181. */
  182. template <typename K, typename V> bool vector_exists(const std::vector<K> &vec, V value) {
  183. auto it = std::find(vec.begin(), vec.end(), value);
  184. if (it != vec.end())
  185. return true;
  186. else
  187. return false;
  188. }
  189. /**
  190. * Erase an index value from a vector
  191. * @param vector: Vector to erase value from
  192. * @param index: Index value to remove
  193. */
  194. template <typename K> void erase_at(std::vector<K>& vector, size_t index) {
  195. if (vector.size() == 1) {
  196. vector.clear();
  197. vector.shrink_to_fit();
  198. } else
  199. vector.erase(vector.begin() + index);
  200. }
  201. /**
  202. * Determine if a value exists in the vector and then erase it
  203. * This will only erase the first occurrence of the value
  204. * @param vector: Vector to erase value from
  205. * @param value: Value to remove
  206. * @return True on removal or false otherwise
  207. */
  208. template <typename K, typename V> bool vector_erase_if_exists(std::vector<K> &vector, V value) {
  209. auto it = std::find(vector.begin(), vector.end(), value);
  210. if (it != vector.end()) {
  211. if (vector.size() == 1) {
  212. vector.clear();
  213. vector.shrink_to_fit();
  214. } else
  215. vector.erase(it);
  216. return true;
  217. }
  218. return false;
  219. }
  220. #if __has_builtin( __builtin_add_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 )
  221. template <typename T> bool safe_addition(T a, T b, T &result) {
  222. return __builtin_add_overflow(a, b, &result);
  223. }
  224. #else
  225. template <typename T> bool safe_addition( T a, T b, T& result ){
  226. bool overflow = false;
  227. if( std::numeric_limits<T>::is_signed ){
  228. if( b < 0 ){
  229. if( a < ( (std::numeric_limits<T>::min)() - b ) ){
  230. overflow = true;
  231. }
  232. }else{
  233. if( a > ( (std::numeric_limits<T>::max)() - b ) ){
  234. overflow = true;
  235. }
  236. }
  237. }else{
  238. if( a > ( (std::numeric_limits<T>::max)() - b ) ){
  239. overflow = true;
  240. }
  241. }
  242. result = a + b;
  243. return overflow;
  244. }
  245. #endif
  246. bool safe_substraction( int64 a, int64 b, int64& result );
  247. bool safe_multiplication( int64 a, int64 b, int64& result );
  248. /**
  249. * Safely add values without overflowing.
  250. * @param a: Holder of value to increment
  251. * @param b: Increment by
  252. * @param cap: Cap value
  253. * @return Result of a + b
  254. */
  255. template <typename T> T safe_addition_cap( T a, T b, T cap ){
  256. T result;
  257. if( rathena::util::safe_addition( a, b, result ) ){
  258. return cap;
  259. }
  260. return std::min(result, cap);
  261. }
  262. template <typename T> void tolower( T& string ){
  263. std::transform( string.begin(), string.end(), string.begin(), ::tolower );
  264. }
  265. /**
  266. * Pad string with arbitrary character in-place
  267. * @param str: String to pad
  268. * @param padding: Padding character
  269. * @param num: Maximum length of padding
  270. */
  271. void string_left_pad_inplace(std::string& str, char padding, size_t num);
  272. /**
  273. * Pad string with arbitrary character
  274. * @param original: String to pad
  275. * @param padding: Padding character
  276. * @param num: Maximum length of padding
  277. *
  278. * @return A copy of original string with padding added
  279. */
  280. std::string string_left_pad(const std::string& original, char padding, size_t num);
  281. /**
  282. * Encode base10 number to base62. Originally by lututui
  283. * @param val: Base10 Number
  284. * @return Base62 string
  285. **/
  286. std::string base62_encode( uint32 val );
  287. }
  288. }
  289. #endif /* UTILILITIES_HPP */