utilities.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  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. * Get a random value from the given vector
  150. * @param vec: Vector to search through
  151. * @return A random value by reference
  152. */
  153. template <typename K> K &vector_random(std::vector<K> &vec) {
  154. auto it = vec.begin();
  155. std::advance( it, rnd_value<size_t>( 0, vec.size() - 1 ) );
  156. return *it;
  157. }
  158. /**
  159. * Get an iterator element
  160. * @param vec: Vector to search through
  161. * @param value: Value wanted
  162. * @return Key value iterator on success or vector end iterator on failure
  163. */
  164. template <typename K, typename V> typename std::vector<K>::iterator vector_get(std::vector<K> &vec, V key) {
  165. return std::find(vec.begin(), vec.end(), key);
  166. }
  167. /**
  168. * Determine if a value exists in the vector
  169. * @param vec: Vector to search through
  170. * @param value: Value wanted
  171. * @return True on success or false on failure
  172. */
  173. template <typename K, typename V> bool vector_exists(const std::vector<K> &vec, V value) {
  174. auto it = std::find(vec.begin(), vec.end(), value);
  175. if (it != vec.end())
  176. return true;
  177. else
  178. return false;
  179. }
  180. /**
  181. * Erase an index value from a vector
  182. * @param vector: Vector to erase value from
  183. * @param index: Index value to remove
  184. */
  185. template <typename K> void erase_at(std::vector<K>& vector, size_t index) {
  186. if (vector.size() == 1) {
  187. vector.clear();
  188. vector.shrink_to_fit();
  189. } else
  190. vector.erase(vector.begin() + index);
  191. }
  192. /**
  193. * Determine if a value exists in the vector and then erase it
  194. * This will only erase the first occurrence of the value
  195. * @param vector: Vector to erase value from
  196. * @param value: Value to remove
  197. * @return True on removal or false otherwise
  198. */
  199. template <typename K, typename V> bool vector_erase_if_exists(std::vector<K> &vector, V value) {
  200. auto it = std::find(vector.begin(), vector.end(), value);
  201. if (it != vector.end()) {
  202. if (vector.size() == 1) {
  203. vector.clear();
  204. vector.shrink_to_fit();
  205. } else
  206. vector.erase(it);
  207. return true;
  208. }
  209. return false;
  210. }
  211. #if __has_builtin( __builtin_add_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 )
  212. template <typename T> bool safe_addition(T a, T b, T &result) {
  213. return __builtin_add_overflow(a, b, &result);
  214. }
  215. #else
  216. template <typename T> bool safe_addition( T a, T b, T& result ){
  217. bool overflow = false;
  218. if( std::numeric_limits<T>::is_signed ){
  219. if( b < 0 ){
  220. if( a < ( (std::numeric_limits<T>::min)() - b ) ){
  221. overflow = true;
  222. }
  223. }else{
  224. if( a > ( (std::numeric_limits<T>::max)() - b ) ){
  225. overflow = true;
  226. }
  227. }
  228. }else{
  229. if( a > ( (std::numeric_limits<T>::max)() - b ) ){
  230. overflow = true;
  231. }
  232. }
  233. result = a + b;
  234. return overflow;
  235. }
  236. #endif
  237. bool safe_substraction( int64 a, int64 b, int64& result );
  238. bool safe_multiplication( int64 a, int64 b, int64& result );
  239. /**
  240. * Safely add values without overflowing.
  241. * @param a: Holder of value to increment
  242. * @param b: Increment by
  243. * @param cap: Cap value
  244. * @return Result of a + b
  245. */
  246. template <typename T> T safe_addition_cap( T a, T b, T cap ){
  247. T result;
  248. if( rathena::util::safe_addition( a, b, result ) ){
  249. return cap;
  250. }else{
  251. return result;
  252. }
  253. }
  254. template <typename T> void tolower( T& string ){
  255. std::transform( string.begin(), string.end(), string.begin(), ::tolower );
  256. }
  257. /**
  258. * Pad string with arbitrary character in-place
  259. * @param str: String to pad
  260. * @param padding: Padding character
  261. * @param num: Maximum length of padding
  262. */
  263. void string_left_pad_inplace(std::string& str, char padding, size_t num);
  264. /**
  265. * Pad string with arbitrary character
  266. * @param original: String to pad
  267. * @param padding: Padding character
  268. * @param num: Maximum length of padding
  269. *
  270. * @return A copy of original string with padding added
  271. */
  272. std::string string_left_pad(const std::string& original, char padding, size_t num);
  273. /**
  274. * Encode base10 number to base62. Originally by lututui
  275. * @param val: Base10 Number
  276. * @return Base62 string
  277. **/
  278. std::string base62_encode( uint32 val );
  279. }
  280. }
  281. #endif /* UTILILITIES_HPP */