rathena/src/common/utilities.cpp
SapitoSucio 55d3c1578c
Itemlink command and integration (#7291)
Co-authored-by: Akkarinage <mike.langford@industrial-illusions.net>
Co-authored-by: Aleos <aleos89@users.noreply.github.com>
Co-authored-by: Atemo <Atemo@users.noreply.github.com>
Co-authored-by: cydh<cydh@users.noreply.github.com>
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
Co-authored-by: secretdataz<secretdataz@users.noreply.github.com>
2022-11-11 18:04:41 +01:00

147 lines
3.7 KiB
C++

// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#include "utilities.hpp"
#include <algorithm>
#include <chrono>
#include <iostream>
#include <numeric> //iota
#include <string>
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
struct cScopeTimer::sPimpl {
std::chrono::steady_clock::time_point start;
std::chrono::steady_clock::time_point end;
sPimpl()
{
start = std::chrono::steady_clock::now();
}
~sPimpl(){
end = std::chrono::steady_clock::now();
std::chrono::microseconds diff = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << " took=" << diff.count() << "ms !\n";
}
};
cScopeTimer::cScopeTimer()
: aPimpl(new sPimpl())
{}
/**
* Calculates the Levenshtein distance of two strings.
* @author http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C.2B.2B
* comparison test was done here http://cpp.sh/2o7w
*/
int levenshtein(const std::string &s1, const std::string &s2)
{
// To change the type this function manipulates and returns, change
// the return type and the types of the two variables below.
int s1len = static_cast<int>(s1.size());
int s2len = static_cast<int>(s2.size());
auto column_start = (decltype(s1len))1;
auto column = new decltype(s1len)[s1len + 1];
std::iota(column + column_start, column + s1len + 1, column_start);
for (auto x = column_start; x <= s2len; x++) {
column[0] = x;
auto last_diagonal = x - column_start;
for (auto y = column_start; y <= s1len; y++) {
auto old_diagonal = column[y];
auto possibilities = {
column[y] + 1,
column[y - 1] + 1,
last_diagonal + (s1[y - 1] == s2[x - 1]? 0 : 1)
};
column[y] = std::min(possibilities);
last_diagonal = old_diagonal;
}
}
auto result = column[s1len];
delete[] column;
return result;
}
bool rathena::util::safe_substraction( int64 a, int64 b, int64& result ){
#if __has_builtin( __builtin_sub_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 )
return __builtin_sub_overflow( a, b, &result );
#else
bool overflow = false;
if( b < 0 ){
if( a > ( INT64_MAX + b ) ){
overflow = true;
}
}else{
if( a < ( INT64_MIN + b ) ){
overflow = true;
}
}
result = a - b;
return overflow;
#endif
}
bool rathena::util::safe_multiplication( int64 a, int64 b, int64& result ){
#if __has_builtin( __builtin_mul_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 )
return __builtin_mul_overflow( a, b, &result );
#else
result = a * b;
if( a > 0 ){
if( b > 0 ){
return result < 0;
}else if( b < 0 ){
return result > 0;
}
}else if( a < 0 ){
if( b > 0 ){
return result > 0;
}else if( b < 0 ){
return result < 0;
}
}
return false;
#endif
}
void rathena::util::string_left_pad_inplace(std::string& str, char padding, size_t num)
{
str.insert(0, min(0, num - str.length()), padding);
}
std::string rathena::util::string_left_pad(const std::string& original, char padding, size_t num)
{
return std::string(num - min(num, original.length()), padding) + original;
}
constexpr char base62_dictionary[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z'
};
std::string rathena::util::base62_encode( uint32 val ){
std::string result = "";
while (val != 0) {
result = base62_dictionary[(val % 62)] + result;
val /= 62;
}
return result;
}