# include <string>
# include <vector>
# include <iomanip>
# include <cstring>
# include <cstdint>
# include "includes/connect_code.hpp"
# include "includes/numeric_base.hpp"
namespace connect_code {
/* Tokenizes a string, based on the given delimiter */
std : : vector < std : : string > tokenize_str ( std : : string str , std : : string delim ) {
std : : vector < std : : string > result ;
/* &str[0] is used to convert an std::string to a char*. I tried using string.data(),
but that appears to return a const char * . */
char * c_str = & str [ 0 ] ;
char * c_delim = & delim [ 0 ] ;
char * tok = strtok ( c_str , c_delim ) ;
while ( tok ! = NULL ) {
result . push_back ( std : : string ( tok ) ) ;
tok = strtok ( NULL , c_delim ) ;
}
return result ;
}
/* Convert an IPv4 address from decimal to dotted decimal notation */
std : : string dec_to_dotted_dec ( std : : string addr ) {
uint32_t addr_val = std : : stoul ( addr ) ; /* 32 bit address */
uint8_t addr_1 = ( addr_val & ( 0xFF < < 24 ) ) > > 24 ; /* First octet (Bitwise AND the address with 255.0.0.0, and shift it to the right to obtain the first octet) */
uint8_t addr_2 = ( addr_val & ( 0xFF < < 16 ) ) > > 16 ;
uint8_t addr_3 = ( addr_val & ( 0xFF < < 8 ) ) > > 8 ;
uint8_t addr_4 = ( addr_val & 0xFF ) ;
std : : string ret_val = std : : string ( std : : to_string ( addr_1 ) + " . " + std : : to_string ( addr_2 ) + " . " + std : : to_string ( addr_3 ) + " . " + std : : to_string ( addr_4 ) ) ;
return ret_val ;
}
/* Convert an IPv4 address from dotted deecimal to decimal */
std : : string dotted_dec_to_dec ( std : : string addr ) {
std : : vector < std : : string > octets = tokenize_str ( addr , " . " ) ;
uint32_t addr_val = ( std : : stoul ( octets [ 0 ] ) < < 24 ) + ( std : : stoul ( octets [ 1 ] ) < < 16 ) + ( std : : stoul ( octets [ 2 ] ) < < 8 ) + ( std : : stoul ( octets [ 3 ] ) ) ;
return std : : to_string ( addr_val ) ;
}
std : : string encode ( std : : string address , std : : string port ) {
/* Convert the address to decimal, and convert that to hex */
std : : string addr_coded = dotted_dec_to_dec ( address ) ;
addr_coded = base_convert ( addr_coded , 10 , 32 ) ;
/* Convert the port to hex */
std : : string port_coded = base_convert ( port , 10 , 32 ) ;
std : : string ret_val = addr_coded + " _ " + port_coded ;
return ret_val ;
}
std : : vector < std : : string > decode ( std : : string connect_code ) {
if ( connect_code . find ( " _ " ) = = std : : string : : npos ) {
throw std : : invalid_argument ( " Invalid code entered. " ) ;
}
std : : vector < std : : string > result = tokenize_str ( connect_code , " _ " ) ; /* Split the string into address and port */
std : : string address = result [ 0 ] ; /* Address (in base 16) */
std : : string port = result [ 1 ] ; /* Port (in base 16) */
/* Base 16 to base 10 - These lines convert the string to a base 10 number, and convert the result back into a string */
address = std : : to_string ( std : : stoul ( address , 0 , 32 ) ) ;
port = std : : to_string ( std : : stoul ( port , 0 , 32 ) ) ;
/* Convert decimal address to dotted decimal */
address = dec_to_dotted_dec ( address ) ;
std : : vector < std : : string > ret_val ;
ret_val . push_back ( address ) ;
ret_val . push_back ( port ) ;
return ret_val ;
}
}