标准c++解析纯真ip数据库

来源:互联网 发布:软件开发团队管理 编辑:程序博客网 时间:2024/05/22 18:32
main.cpp文件部分:
#include <string>
#include <iostream>
#include "ipaddress.hpp"
#include <fstream>
#include <locale>

int main(int argc, char* argv[])
{
try
  {   
    ipaddress::ip_contain file_ip("QQWry.Dat");

    file_ip.load();

    std::ofstream out_file("address.txt");

    out_file<<file_ip;

    std::cout<<"successful"<<std::endl;
  }
 catch(const std::exception& e)
   {
     std::cout<<e.what()<<std::endl;
   }
 catch(...)
   {
     std::cout<<"unkown error occur"<<std::endl;
   }
  return 0;
}

ipaddress.hpp文件部分:
#ifndef IP_ADDRESS_HPP
#define IP_ADDRESS_HPP
#include <boost/foreach.hpp>
#include <stdio.h>
#include <iterator>
#include <algorithm>
#include <arpa/inet.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <exception>
#include <vector>
#include <iconv.h>
namespace ipaddress
{
  bool trans_code(const std::string& src, std::string& dest)
  {
    iconv_t cd = iconv_open("utf-8","gb2312");
    if (cd == 0)
      {
    return false;
      }
    char out[1024];
    size_t out_buf = 1024;
    
    memset(out, 0, out_buf);
    size_t in_buf = src.size();
    char in[in_buf];
    for (int i=0; i<in_buf; i++)
      {
    in[i] = src[i];
      }
        
    char* ptr_in = in;
    char* ptr_out = out;
    if (iconv(cd, &ptr_in, &in_buf, &ptr_out, &out_buf) == -1)
      {
    iconv_close(cd);    
    return false;
      }
    else
      {
    iconv_close(cd);    
    dest = std::string(out, 1024-out_buf);    
    return true;
      }
  }

  class file_error:public std::exception
  {
  public:
    file_error(std::string error):_error(error)
    {
    }

    virtual ~file_error()throw()
    {
    }

    virtual const char* what()const throw()
    {
      return _error.c_str();
    }

  private:
    std::string _error;
  };

  std::string trans_uint_string(unsigned int ip)
  {
    in_addr ina;
    ina.s_addr = ntohl(ip);
    return std::string( inet_ntoa(ina) );
  }

  class ip_record
  {
  public:
    ip_record()
    {
    }
    ip_record(const std::string& begin_ip, const std::string& end_ip, const std::string& country, const std::string& city):_begin_ip(begin_ip),_end_ip(end_ip), _country(country),_city(city)
    {
    }
    ~ip_record()
    {
    }
    friend std::ostream& operator<<(std::ostream& os, const ip_record& target)
    {
      os<<target._begin_ip<<std::endl<<target._end_ip<<std::endl<<target._city<<std::endl<<target._country<<std::endl;
      return os;
    }
    friend std::istream& operator>>(std::istream& is, ip_record& target)
    {
      is>>target._begin_ip>>target._end_ip>>target._city>>target._country;
      return is;
    }
    const ip_record& operator=(const ip_record& target)
    {
      _begin_ip = target._begin_ip;
      _end_ip   = target._end_ip;
      _city     = target._city;
      _country  = target._country;
      return target;
    }
    std::string get_begin_ip(void)const
    {
      return _begin_ip;
    }

    std::string get_end_ip(void)const
    {
      return _end_ip;
    }

    std::string get_city(void)const
    {
      return _city;
    }

    std::string get_country(void)const
    {
      return _country;
    }

    void set_begin_ip(const std::string& begin_ip)
    {
      _begin_ip = begin_ip;
    }

    void set_end_ip(const std::string& end_ip)
    {
      _end_ip = end_ip;
    }

    void set_country(const std::string& country)
    {
      _country = country;
    }

    void set_city(const std::string& city)
    {
      _city = city;
    }

    bool is_in(const std::string& ip)
    {
      if ( (ip >= _begin_ip) && (ip <= _end_ip) )
    {
      return true;
    }
      else
    {
      return false;
    }
    }

  private:
    std::string _begin_ip;
    std::string _end_ip;
    std::string _city;
    std::string _country;
  };
 
  class ip_contain
  {    
  public:
    ip_contain()
    {
    }
    ip_contain(const std::string& file_name)throw(file_error)
    {
      try
    {
      open_file(file_name);
    }
      catch(...)
    {
      throw;
    }     
    }

    ~ip_contain()
    {
    }

    int size(void)const
    {
      return _ip_link.size();
    }

    ip_record operator[](int index)const
    {
      return _ip_link[index];
    }

    const std::vector<ip_record>& get_ip_link(void)
    {
      return _ip_link;
    }

    void load(void)throw(file_error)
    {
      try
    {
      load_from();
    }
      catch(...)
    {
      throw;
    }
    }

    void load(const std::string& file_name)throw(file_error)
    {
      try
    {
      open_file(file_name);
      load_from();
    }
      catch(...)
    {
      throw;
    }
    }    

    friend std::ostream& operator<<(std::ostream& os, ip_contain& target)
    {      
      std::copy(target._ip_link.begin(), target._ip_link.end(), std::ostream_iterator<ip_record>(os));
      return os;
    }

    friend std::istream& operator>>(std::istream& is, ip_contain& target)
    {
      ip_record it;
      while( !is.eof() )
    {
      is>>it;
      target._ip_link.push_back(it);
    }
      return is;
    }
  protected:
    void open_file(const std::string& file_name)throw(file_error)
    {
      _input_file.open(file_name.c_str(), std::ios::binary);
      if (!_input_file)
    {
      throw file_error("can not open "+file_name);
    }      
    }
    void load_from(void)throw(file_error)
    {      
      try
    {
      unsigned int begin_index,end_index;
      _input_file.seekg(0,std::ios::beg);
      _input_file.read((char*)&begin_index,4);
      _input_file.read((char*)&end_index,4);
      while (begin_index < end_index)
        {          
          read_ip_record(begin_index);
          begin_index += 7;          
        }
    }
      catch(...)
    {
      throw;
    }
    }

    void read_string(std::string& result)
    {
      char ch;
      std::string temp;
      _input_file.read(&ch, sizeof(ch));
      while (ch != 0)
    {
      temp += ch;
      _input_file.read(&ch, sizeof(ch));
    }

      if (!trans_code(temp, result))
    {
      result = "trans failure";
    }      
    }

    void read_country(std::string& country, char mode=0)//mode=0 direct
    {
      if (mode == 0x01)//no eara city behind
    {
      unsigned int countryoff = 0;
      _input_file.read((char*)&countryoff, 3);
      char futher_mode;
      _input_file.seekg(countryoff, std::ios::beg);
      _input_file.read(&futher_mode, 1);
      read_country(country, futher_mode);
    }
      else if(mode == 0x02)//exist city behind, must be restore old_pos
    {
      unsigned int off = 0;
      _input_file.read((char*)&off, 3);
      unsigned int old_pos = _input_file.tellg();
      _input_file.seekg(off, std::ios::beg);
      read_string(country);
      _input_file.seekg(old_pos, std::ios::beg);
    }
      else //direct mode, exist city behind,but order
    {
      _input_file.seekg(-1, std::ios::cur);
      read_string(country);
    }
    }

    void read_eara(std::string& city)
    {
      char flag;
      _input_file.read(&flag, 1);
      if ((flag == 0x01) || (flag == 0x02))
    {
      unsigned int off = 0;
      _input_file.read((char*)&off, 3);
      if (off == 0)
        {
          city = "unkown eara";
        }
      else
        {
          _input_file.seekg(off, std::ios::beg);
          read_string(city);
        }
    }
      else
    {
      _input_file.seekg(-1, std::ios::cur);
      read_string(city);
    }
    }

    void read_ip_record(unsigned int pos)
    {      
      ip_record it;
      unsigned int begin_ip,end_ip;
            
      _input_file.seekg(pos, std::ios::beg);
      _input_file.read((char*)&begin_ip,4);
      it.set_begin_ip( trans_uint_string(begin_ip) );
            
      unsigned int ptr_ip_record = 0;
      _input_file.seekg(pos+4, std::ios::beg);
      _input_file.read((char*)&ptr_ip_record,3);
            
      _input_file.seekg(ptr_ip_record, std::ios::beg);
      _input_file.read((char*)&end_ip,4);
      it.set_end_ip( trans_uint_string(end_ip) );
            
      std::string country,city;
      char mode;
      _input_file.read(&mode,1);
      
      read_country(country, mode);
      read_eara(city);
      
      it.set_country(country);
      it.set_city(city);      
      _ip_link.push_back(it);
    }   
  private:
    std::ifstream _input_file;
    std::vector<ip_record> _ip_link;    
  };
}
#endif