nocopyable

//以前的那种是语言级别的,这个是编译器级别的
#pragma once


/*
原理:
派生类的拷贝构造和赋值,肯定要先调用基类的拷贝构造跟赋值
采用这种方式,可以让派生类直接无法拷贝构造跟赋值

为什么不在子类里面自己delete呢?
优雅呗哈哈哈
*/

//作为一个没有拷贝构造函数的基类
class nocpoyable{
public:
    nocpoyable(const nocpoyable&) = delete;
    void operator=(const nocpoyable&) = delete;

protected:  //派生类可以访问,外部不能访问
    nocpoyable() = default; //默认实现
    ~nocpoyable() = default;
};

Logger

#pragma once

#include<string>

#include"nocopyable.hpp"


//模板方法模式
#define LOG_INFO(LogmsgFormat,...)\
    do\
    {\
        Logger &logger = Logger::instance();\
        logger.setLogLevel(INFO);\
        char buf[1024] = {0};\
        snprintf(buf,1024,LogmsgFormat,##__VA_ARGS__);\
        logger.log(buf);\
    }while(0)

#define LOG_ERROR(LogmsgFormat,...)\
    do\
    {\
        Logger &logger = Logger::instance();\
        logger.setLogLevel(ERROR);\
        char buf[1024] = {0};\
        snprintf(buf,1024,LogmsgFormat,##__VA_ARGS__);\
        logger.log(buf);\
    }while(0)

//为了防止一些意想不到的错误,都使用do while(0)
//在这里面不能插注释!!!
//斜杠之后连空格都不能有
#define LOG_FATAL(LogmsgFormat,...)\
    do{\
        Logger &logger = Logger::instance();\
        logger.setLogLevel(FATAL);\
        char buf[1024] = {0};\
        snprintf(buf,1024,LogmsgFormat,##__VA_ARGS__);\
        logger.log(buf);\
    }while(0)

#ifdef MUDEBUG
#define LOG_DEBUG(LogmsgFormat,...)\
    do{\
        Logger &logger = Logger::instance();\
        logger.setLogLevel(DEBUG);\
        char buf[1024] = {0};\
        snprintf(buf,1024,LogmsgFormat,##__VA_ARGS__);\
        logger.log(buf);\
    }while(0)
#else
    #define LOG_DEBUG(LogmsgFormat,...)
#endif


//定义日志级别
enum Loglevel{
    INFO,   //普通信息
    ERROR,  //错误信息
    FATAL,  //core信息
    DEBUG,  //debug信息
};

class Logger:nocpoyable{
public:
    //获取单例
    static Logger& instance();

    //设置日志级别
    void setLogLevel(int level);

    //写日志
    void log(std::string msg);

private:
    int loglevel_;
    //设置单例
    Logger(){}
};
#include"logger.hpp"
#include"timestamp.hpp"

#include<iostream>


//单例模式 懒汉
Logger& Logger::instance(){
    static Logger logger;
    return logger;
}

//设置日志级别
void Logger::setLogLevel(int level){
    loglevel_ = level;
}

//写日志    [级别]:time:msg
void Logger::log(std::string msg){
    switch (loglevel_)
    {
    case INFO:
        std::cout<<"[INFO]:";
        break;
    case ERROR:
        std::cout<<"[ERRER]:";
        break;
    case FATAL:
        std::cout<<"[FATAL]:";
        break;
    case DEBUG:
        std::cout<<"[DEBUG]:";
        break;
    
    default:
        break;
    }

    timestamp tts;
    std::cout<<tts.toString()<<std::endl;
}

Timestamp

#pragma once

#include<iostream>

class timestamp{
public:
    timestamp();

    //待参数的构造函数都带上了explicit关键字,为什么呢?
    //其实有时候代码表现出来的并不是你想的那样
    explicit timestamp(int64_t microSecondsSinceEpoch);
    static timestamp now();
    std::string toString() const;

private:
    int64_t microSecondsSinceEpoch_;
};
#include"timestamp.hpp"

#include<time.h>

timestamp::timestamp()
    :microSecondsSinceEpoch_(0)
{

}

timestamp::timestamp(int64_t microSecondsSinceEpoch)
    :microSecondsSinceEpoch_(microSecondsSinceEpoch)
{

}

timestamp timestamp::now(){
    return timestamp(time(NULL));
}

std::string timestamp::toString() const{
    char buf[128] = {0};
    tm* tm_time = localtime(&microSecondsSinceEpoch_);
    snprintf(buf,128,"%4d/%02d/%02d %02d:%02d:%02d",
        tm_time->tm_year+1900,tm_time->tm_mon+1,tm_time->tm_mday,
        tm_time->tm_hour,tm_time->tm_min,tm_time->tm_sec);

    return buf;
}

InetAddr

#pragma once

#include<arpa/inet.h>
#include<netinet/in.h>
#include<string>

class InetAddress{
public:
    explicit InetAddress(uint16_t port,std::string ip = "127.0.0.1");
    explicit InetAddress(const sockaddr_in &addr)
        :addr_(addr)
    {}

    std::string toIp() const;
    std::string toIpPort() const;
    uint16_t toPort() const;

private:
    sockaddr_in addr_;
};
#include"InetAddr.hpp"

#include<string.h>

InetAddress::InetAddress(uint16_t port,std::string ip){
    bzero(&addr_,sizeof addr_); //居然还能这样写,以前都不知道
    addr_.sin_family = AF_INET;
    addr_.sin_port = htons(port);   //转换网络字节序
    //host to net short
    addr_.sin_addr.s_addr = inet_addr(ip.c_str()); 
}

std::string InetAddress::toIp() const{
    char buf[64] = {0};
    //这里我也不知道为什么要设置为全局作用域下的
    ::inet_ntop(AF_INET,&addr_.sin_addr,buf,sizeof(buf));
    
    return buf;
}

std::string InetAddress::toIpPort() const{
    char buf[64] = {0};
    //这里我也不知道为什么要设置为全局作用域下的
    ::inet_ntop(AF_INET,&addr_.sin_addr,buf,sizeof(buf));
    
    size_t end = strlen(buf);
    uint16_t port = ntohs(addr_.sin_port);

    sprintf(buf+end, ":%u", port);
    return buf;
}

uint16_t InetAddress::toPort() const{
    return ntohs(addr_.sin_port);
}


// #include<iostream>
// int main(){
//     InetAddress addr(6666);
//     std::cout<<addr.toIpPort()<<std::endl;
// }