1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
| class AddressFactory
{
public:
AbstractAddress* createAddress(std::string const & addressString)
{
/* les 3 étapes peuvent se faire ici */
/* mais, comme j'aime respecter SRP, ca devient */
//première étape: on remplace les caractères
std::string temp(replacePoints(addressString));
//deuxième étape : on récupère les valeurs numériques
computeStringValues(temp);
// troisième étape : on crée l'adresse du type adéquat et on la renvoie
if(values_.size() == 4)
return createIpv4();
else if(values_.size() == 6)
return createMac();
else if (std::count_if(values_.begin(),values_.end(),
[](unsigned short i){return i<0xFF;}) != 0)
return createIpv6();
return createMac();
}
private:
std::string replacePoint(std::string const & toChange) const
{
std::string temp(toChange);
/* effectue le remplacement de : par un espace pour Mac et IPV6 */
std::replace_if(temp.begin(), temp.end(),
[](const char c){return c ==':';},' ');
/* effectue le remplacement de . par un espace pour IPV4 */
std::replace_if(temp.begin(), temp.end(),
[](const char c){return c =='.';},' ');
return temp;
}
void computeStringValues(std::string const & toCompute)
{
size_t count = std::count_if(toCompute.begin(),
toCompute.end(),
[](const char c){return c ==' ';});
switch(count)
{
case 3:
computeDecimalValues(toCompute);
break;
case 5:
case 7:
computeHexaValues(toCompute)
break;
default:
throw BadStringFormat(); // à implémenter par toi meme
}
}
void computeDecimalValues(std::string const & toCompute)
{
std::stringstream ss;
ss<<toCompute;
unsigned short recup;
while(ss>>recup)
values_.push_back(recup);
}
void computeDecimalValues(std::string const & toCompute)
{
std::stringstream ss;
ss<<toCompute;
unsigned short recup;
while(ss>>std::hex>>recup)
values_.push_back(recup);
}
AbstractAddress * createIpv4() const
{
/* Une adresse IPV4 peut etre représentée par un entier
* non signé codé sur 32 bits.
*
* Tout ce qu'il faut faire, c'est donc de créer cette valeur.
* Par facilité, je la crées au format "little endian", c'est à dire
* que les bits de poids fort représentent les valeurs les plus
* importantes
*/
uint32_t value = 0;
for(auto i : values_)
{
value<<8; // on décale tout de 8 bits
value = value | i; // et on rajoute la valeur de l'élément actuel
}
return new Ipv4Address(value);
}
AbstractAddress * createIpv6() const
{
/* Même principe pour les IPV6, mais sur un entier codé sur 128 bits
*/
if(values_.size() != 6)
throw BadValueCountForIpv6(); // pour le cas où je me serais trompé
uint128_t value = 0;
for(auto i : values_)
{
value<<16; //ici, on décale tout de 16 bits car on peut avoir des valeurs > 0xFF
value = value | i; // et on rajoute la valeur de l'élément actuel
}
return new Ipv6Address(value);
}
AbstractAddress * createMac() const
{
if( values_.size() != 6
&& values_.size() != 8)
throw BadValueCountForMac(); // pour le cas où je me serais trompé
/* EUI-48 est composé de 48 bits alors que EUI-64 bits est composé
* de 64 bits.
* Mais comme on ne dispose pas d'un type codé sur 48 bits, nous
* allons tout représenter sur la forme d'un entier 64 bits.
* Nous allons "simplement" déterminer la norme effective sur base
* du nombre de valeurs dont on dispose et la représenter sous la
* forme d'une énumértion ;)
*/
uint64_t value = 0;
for(auto i : values_)
{
value<<8 des valeurs > 0xFF
value = value | i; // et on rajoute la valeur de l'élément actuel
}
return new MacAddress(value, values_.size() == 6? EUI48 : EUI64 );
}
std::vetor<unsigned_short> values_;
}; |
Partager