00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef TORRENT_PEER_ID_HPP_INCLUDED
00034 #define TORRENT_PEER_ID_HPP_INCLUDED
00035
00036 #include <iostream>
00037 #include <iomanip>
00038 #include <cassert>
00039 #include <cctype>
00040 #include <algorithm>
00041 #include <string>
00042
00043 #include "libtorrent/config.hpp"
00044
00045 namespace libtorrent
00046 {
00047
00048 class TORRENT_EXPORT big_number
00049 {
00050
00051 struct private_pointer {};
00052
00053 enum { number_size = 20 };
00054 public:
00055 enum { size = number_size };
00056
00057 big_number() {}
00058
00059 big_number(std::string const& s)
00060 {
00061 int sl = int(s.size()) < size ? int(s.size()) : size;
00062 std::memcpy(m_number, &s[0], sl);
00063 }
00064
00065
00066 big_number(private_pointer*) { clear(); }
00067
00068 void clear()
00069 {
00070 std::fill(m_number,m_number+number_size,0);
00071 }
00072
00073 bool is_all_zeros() const
00074 {
00075 return std::count(m_number,m_number+number_size,0) == number_size;
00076 }
00077
00078 bool operator==(big_number const& n) const
00079 {
00080 return std::equal(n.m_number, n.m_number+number_size, m_number);
00081 }
00082
00083 bool operator!=(big_number const& n) const
00084 {
00085 return !std::equal(n.m_number, n.m_number+number_size, m_number);
00086 }
00087
00088 bool operator<(big_number const& n) const
00089 {
00090 for (int i = 0; i < number_size; ++i)
00091 {
00092 if (m_number[i] < n.m_number[i]) return true;
00093 if (m_number[i] > n.m_number[i]) return false;
00094 }
00095 return false;
00096 }
00097
00098 big_number operator~()
00099 {
00100 big_number ret;
00101 for (int i = 0; i< number_size; ++i)
00102 ret.m_number[i] = ~m_number[i];
00103 return ret;
00104 }
00105
00106 big_number& operator &= (big_number const& n)
00107 {
00108 for (int i = 0; i< number_size; ++i)
00109 m_number[i] &= n.m_number[i];
00110 return *this;
00111 }
00112
00113 big_number& operator |= (big_number const& n)
00114 {
00115 for (int i = 0; i< number_size; ++i)
00116 m_number[i] |= n.m_number[i];
00117 return *this;
00118 }
00119
00120 unsigned char& operator[](int i)
00121 { assert(i >= 0 && i < number_size); return m_number[i]; }
00122
00123 unsigned char const& operator[](int i) const
00124 { assert(i >= 0 && i < number_size); return m_number[i]; }
00125
00126 typedef const unsigned char* const_iterator;
00127 typedef unsigned char* iterator;
00128
00129 const_iterator begin() const { return m_number; }
00130 const_iterator end() const { return m_number+number_size; }
00131
00132 iterator begin() { return m_number; }
00133 iterator end() { return m_number+number_size; }
00134
00135 private:
00136
00137 unsigned char m_number[number_size];
00138
00139 };
00140
00141 typedef big_number peer_id;
00142 typedef big_number sha1_hash;
00143
00144 inline std::ostream& operator<<(std::ostream& os, big_number const& peer)
00145 {
00146 for (big_number::const_iterator i = peer.begin();
00147 i != peer.end(); ++i)
00148 {
00149 os << std::hex << std::setw(2) << std::setfill('0')
00150 << static_cast<unsigned int>(*i);
00151 }
00152 os << std::dec << std::setfill(' ');
00153 return os;
00154 }
00155
00156 inline std::istream& operator>>(std::istream& is, big_number& peer)
00157 {
00158 using namespace std;
00159
00160 for (big_number::iterator i = peer.begin();
00161 i != peer.end(); ++i)
00162 {
00163 char c[2];
00164 is >> c[0] >> c[1];
00165 c[0] = tolower(c[0]);
00166 c[1] = tolower(c[1]);
00167 if (
00168 ((c[0] < '0' || c[0] > '9') && (c[0] < 'a' || c[0] > 'f'))
00169 || ((c[1] < '0' || c[1] > '9') && (c[1] < 'a' || c[1] > 'f'))
00170 || is.fail())
00171 {
00172 is.setstate(ios_base::failbit);
00173 return is;
00174 }
00175 *i = ((isdigit(c[0])?c[0]-'0':c[0]-'a'+10) << 4)
00176 + (isdigit(c[1])?c[1]-'0':c[1]-'a'+10);
00177 }
00178 return is;
00179 }
00180
00181 }
00182
00183 #endif // TORRENT_PEER_ID_HPP_INCLUDED
00184