- 论坛徽章:
- 44
|
本帖最后由 windoze 于 2015-10-17 01:54 编辑
嗯,lz的这个问题我还真的想了想,发现还是需要写点代码的
https://gist.github.com/windoze/ ... #file-gistfile1-txt
- #include <cstdint>
- #include <array>
- #include <vector>
- #include <iostream>
- #include <random>
- inline constexpr uint32_t subnet_mask(int len) {
- return 0xFFFFFFFF >> (32-len) << (32-len);
- }
- inline uint8_t read_segment(const std::string &s, size_t start_pos) {
- return 0;
- }
- struct IP_addr {
- uint32_t data;
-
- // NOTE: Hardcoded little endian u32
- uint8_t &operator[](size_t index)
- { return reinterpret_cast<uint8_t *>(&data)[3-index]; }
-
- // NOTE: Hardcoded little endian u32
- const uint8_t &operator[](size_t index) const
- { return reinterpret_cast<const uint8_t *>(&data)[3-index]; }
-
- IP_addr mask(int len) const { return IP_addr{data & subnet_mask(len)}; }
- template<typename Iterator>
- static IP_addr parse(Iterator begin, Iterator end) {
- IP_addr ret{0};
- size_t index = 0;
- while (begin!=end) {
- if (isdigit((unsigned char)*begin)) {
- ret[index] *= 10;
- ret[index] += *begin - '0';
- } else {
- ++index;
- }
- ++begin;
- }
- return ret;
- }
- };
- inline std::ostream &operator << (std::ostream &os, const IP_addr &addr) {
- os << int(addr[0]) << '.' << int(addr[1]) << '.' << int(addr[2]) << '.' << int(addr[3]);
- return os;
- }
- struct IP_subnet {
- IP_addr subnet_base;
- int mask_len;
-
- size_t size() const {
- // .0 and .255 are not valid IP address unless it's a single address subnet
- if (mask_len==32) {
- return 1;
- }
- return (~subnet_mask(mask_len)) + 1 - 2;
- }
-
- IP_addr operator[](size_t index) {
- if(mask_len==32)
- return IP_addr{static_cast<uint32_t>(subnet_base.data+index)};
- return IP_addr{static_cast<uint32_t>(subnet_base.data+index+1)};
- }
-
- template<typename Iterator>
- static IP_subnet parse(Iterator begin, Iterator end) {
- IP_subnet ret{0, 0};
- Iterator slash=std::find(begin, end, '/');
- ret.subnet_base=IP_addr::parse(begin, slash);
- ret.mask_len=0;
- ++slash;
- while(slash!=end) {
- ret.mask_len *= 10;
- ret.mask_len += *slash - '0';
- ++slash;
- }
- ret.subnet_base=ret.subnet_base.mask(ret.mask_len);
- return ret;
- }
- };
- template<typename InputContainer, typename OutputContainer>
- size_t random_pick(InputContainer input, OutputContainer &output) {
- size_t n=input.size();
- size_t k=output.size();
- k=std::min(n, k);
- for (size_t i=0; i<k; i++) {
- output[i]=input[i];
- }
- std::random_device rd;
- std::default_random_engine e(rd());
-
- for (size_t i=k; i<n; i++) {
- size_t j=std::uniform_int_distribution<size_t>(0, i+1)(e);
- if(j<k)
- output[j]=input[i];
- }
- return k;
- }
- inline std::ostream &operator << (std::ostream &os, const IP_subnet &subnet) {
- os << subnet.subnet_base << '/' << subnet.mask_len;
- return os;
- }
- int main(int argc, const char * argv[]) {
- std::string ip("192.168.2.234");
- IP_addr addr=IP_addr::parse(ip.begin(), ip.end());
- std::cout << addr << std::endl;
- std::string ip_subnet("192.168.2.58/24");
- // parse会自动将这个子网修正为192.168.2.0/24
- IP_subnet sn=IP_subnet::parse(ip_subnet.begin(), ip_subnet.end());
- std::cout <<sn << std::endl;
- std::cout <<sn[0] << std::endl;
- std::vector<IP_addr> out(20);
- random_pick(sn, out);
- std::cout << "---------------------\n";
- for(auto &&e: out) {
- std::cout << e << std::endl;
- }
- return 0;
- }
复制代码 |
|