Phone number regular expression

Phone number regular expression

  • ChinaMain11Mobile3Y2018Mobile
"(^((13[0-9])|(14[5,7,9])|(15[0-3,5-9])"
"|166|(17[0,1,3,5-8])|(18[0-9])|(19[8-9])))-?\\d{4}-?\\d{4}$"
  • ChinaMain11Mobile3Y2018Mobile86
"^((\\+86)|(86))?-?"
"((13[0-9])|(14[5,7,9])|(15[0-3,5-9])"
"|166|(17[0,1,3,5-8])|(18[0-9])|(19[8-9]))-?\\d{4}-?\\d{4}$"
  • ChinaMainPhone
"(^0\\d{2,3})?-?\\d{7,8}$"
  • LesserNums11Mobile
// "^\\d{11}$"

"^\\d{3}-?\\d{4}-?\\d{4}$"
  • LesserPhone
"^\\d+$"

Part of phone number validator implementation in C++

Full code and test cases see

struct PhoneNumber final {
    /**
     * Phone number specification
     * MDN号码的结构如下: CC + MAC + H0 H1 H2 H3 + ABCD 其中:
     * - 【CC】: 国家码,中国使用86。
     * - 【MAC】: 移动接入码,本网采用网号方案,为133。
     * - 【H0H1H2H3】: HLR识别码,由运营商统一分配。
     * - 【ABCD】: 移动用户号,由各HLR自行分配。
     */
    enum class Spec {
        /**
         * @sa https://baike.baidu.com/item/%E6%89%8B%E6%9C%BA%E5%8F%B7%E7%A0%81
         * 电信 联通 移动 + 2018
         * - 中国电信号段
         *   133 149 153 173 177 180 181 189 199
         * - 中国联通号段
         *   130 131 132 145 155 156 166 171 175 176 185 186
         * - 中国移动号段
         *   134(0-8) 135 136 137 138 139 147 150 151 152 157 158 159 178
         *   182 183 184 187 188 198
         *
         * - 其他号段
         *   14 号段以前为上网卡专属号段 如中国联通的是 145 中国移动的是 147 等等
         *   虚拟运营商
         *   - 电信
         *     1700 1701 1702
         *   - 联通
         *     1704 1707 1708 1709 171
         *   - 移动
         *     1703 1705 1706
         *   - 卫星通信
         *     1349
         *
         * Pattern:
         * - nnnnnnnnnnn
         * - nnn-nnnn-nnnn
         * - nnn-nnnnnnnn
         * - nnnnnnn-nnnn
         */
        ChinaMain11Mobile3Y2018Mobile   = 0,
        /**
         * Pattern:
         * - nnnnnnnnnnn
         * - nnn-nnnn-nnnn
         * - nnn-nnnnnnnn
         * - nnnnnnn-nnnn
         * - 86nnnnnnnnnnn
         * - 86-nnnnnnnnnnn
         * - 86-nnn-nnnn-nnnn
         * - 86-nnn-nnnnnnnn
         * - 86-nnn-nnnn-nnnn
         * - +86nnnnnnnnnnn
         * - +86-nnnnnnnnnnn
         * - +86-nnn-nnnn-nnnn
         * - +86-nnn-nnnnnnnn
         * - +86-nnn-nnnn-nnnn
         */
        ChinaMain11Mobile3Y2018Mobile86 = 1,
        /**
         * 区号+号码,区号以 0 开头 3 位或 4 位
         * 号码由 7 位或 8 位数字组成
         * 区号与号码之间可以无连接符 也可以 - 连接
         * Pattern:
         * - 0nnnnnnnnn
         * - 0nn-nnnnnnn
         * - 0nnnnnnnnnn
         * - 0nnn-nnnnnnn
         */
        ChinaMainPhone                  = 10,
        /**
         * Pattern:
         * - nnnnnnnnnnn
         * - nnn-nnnn-nnnn
         */
        LesserNums11Mobile               = 98,
        /**
         * Pattern: n...
         * @note remove all +/- first
         */
        LesserPhone                      = 99,
    };
    ...
};

See also

一个简单实用的 C++ logger

一个简单实用的 C++ logger

  • Log4cxx like, more powerful and slight stream logger
  • Thread-safe and with max log size limit(deque old logs when full)
  • Full ans esay set...()interfaces
  • Logging hook callback and tag(name) filter support
  • Dynamic log level
  • Friendly and source tarceable logger helper support

Full code, example and release package see:

Part code:

constexpr char const* kPrimaryDefaultLogFile = "logger.log";
constexpr uint32_t kMinLogSize = 8192;
/// 256 MB / 128 MB
constexpr uint32_t kDefaultLogSize = sizeof(long) * 32 * 1024 * 1024;
struct Logger {
    /// Output type
    enum Output: uint32_t {
        CoutOrCerr = 0x1,
        File       = 0x2,
        Both       = 0x3,
    };
    /// If 0 => when get logger not change current or default
    using Outputs = Flags<Output>;
    /// Callback when set when append
    using AppendCallback = std::function<void(
        std::string const& name,
        LogLevel const& logLevel,
        std::string const& msg)>;
    /// Dtor to auto finish logger
    virtual ~Logger() noexcept;
    // Global configs
    /// Set default logger, set only when path not empty
    static inline void setDefaultLogger(std::string const& path) noexcept;
    static inline std::string getDefaultLogger() noexcept;
    /**
     * Get a Logger instance
     * @param spinOnceLogLevel If not Unchange, will be use once
     * @param path Logger filename, if empty then will get a default Logger
     * @param outputs output config, used when create logger, if 0 then use
     * default or current exists
     */
    static Logger& getLogger(
        LogLevel const& spinOnceLogLevel = LogLevel::Unchange,
        std::string const& path = "",
        Outputs const& outputs = Outputs{}) noexcept;
    static inline Logger& getFatal(
        std::string const& path = "",
        Outputs const& outputs = Outputs{}) noexcept;
    static inline Logger& getError(
        std::string const& path = "",
        Outputs const& outputs = Outputs{}) noexcept;
    static inline Logger& getWarning(
        std::string const& path = "",
        Outputs const& outputs = Outputs{}) noexcept;
    static inline Logger& getNote(
        std::string const& path = "",
        Outputs const& outputs = Outputs{}) noexcept;
    static inline Logger& getInfo(
        std::string const& path = "",
        Outputs const& outputs = Outputs{}) noexcept;
    static inline Logger& getTrace(
        std::string const& path = "",
        Outputs const& outputs = Outputs{}) noexcept;
    static inline Logger& getDebug(
        std::string const& path = "",
        Outputs const& outputs = Outputs{}) noexcept;
    static inline Logger& getDetail(
        std::string const& path = "",
        Outputs const& outputs = Outputs{}) noexcept;
    /// Release a logger
    static void releaseLogger(std::string const& file) noexcept;
    // Instance config
    void setLogLevel(LogLevel const& logLevel) noexcept;
    /// Toggle log level
    LogLevel toggleLogLevel() noexcept;
    /**
     * Set max log size
     * - If < 0 keep current max
     * - If < kMinLogSize use kMinLogSize
     */
    void setMaxSize(int32_t const maxSize) noexcept;
    inline void setOutputs(Outputs const& o) noexcept;
    inline void setAppendCallback(AppendCallback const& ac) noexcept;
    inline void enableIdx(bool const enable) noexcept;
    inline void enableTid(bool const enable) noexcept;
    /// @note copy
    std::set<std::string> getAcNameFilters() const noexcept;
    bool hasAcNameFilter(std::string const& acNameFilter) const noexcept;
    bool addAcNameFilter(std::string const& acNameFilter) noexcept;
    bool removeAcNameFilter(std::string const& acNameFilter) noexcept;
    void clearAcNameFilters() noexcept;
    /// Limit log size
    void shrinkToFit() noexcept;
    /// Check if log instance valid
    inline operator bool() const noexcept;
    /// @note Only check log level
    inline bool isLogable(LogLevel const& ll) const noexcept;
    inline LogLevel getLogLevel() const noexcept;
    /**
     * Reset logger file
     * @note
     * - When param valid => will always open or reopen
     * - When param invalid => will use default or not-reopen
     */
    int64_t reset(bool const trunc = false) noexcept;
    /// Append name + file + line + msg
    int append(
        char const* const name,
        char const* const file,
        int const line,
        std::string const& msg,
        LogLevel const& logLevel) noexcept;
    /// Append a string msg
    int append(std::string const& msg, LogLevel const& logLevel) noexcept;
    // Logging methods
    // f
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& f(T const& msg)
        noexcept;
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& f(
        std::string const& name, T const& msg) noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& f(T const& msg)
        noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& f(
        std::string const& name, T const& msg) noexcept;
    template<uint32_t sz> Logger& f(const char(&msg)[sz]) noexcept;
    template<uint32_t sz> Logger& f(
        std::string const& name, const char(&msg)[sz]) noexcept;
    // e
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& e(T const& msg)
        noexcept;
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& e(
        std::string const& name, T const& msg) noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& e(T const& msg)
        noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& e(
        std::string const& name, T const& msg) noexcept;
    template<uint32_t sz> Logger& e(char const(&msg)[sz]) noexcept;
    template<uint32_t sz> Logger& e(
        std::string const& name, char const(&msg)[sz]) noexcept;
    // w
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& w(T const& msg)
        noexcept;
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& w(
        std::string const& name, T const& msg) noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& w(T const& msg)
        noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& w(
        std::string const& name, T const& msg) noexcept;
    template<uint32_t sz> Logger& w(char const(&msg)[sz]) noexcept;
    template<uint32_t sz> Logger& w(
        std::string const& name, char const(&msg)[sz]) noexcept;
    // n
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& n(T const& msg)
        noexcept;
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& n(
        std::string const& name, T const& msg) noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& n(T const& msg)
        noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& n(
        std::string const& name, T const& msg) noexcept;
    template<uint32_t sz> Logger& n(char const(&msg)[sz]) noexcept;
    template<uint32_t sz> Logger& n(
        std::string const& name, char const(&msg)[sz]) noexcept;
    // i
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& i(T const& msg)
        noexcept;
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& i(
        std::string const& name, T const& msg) noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& i(T const& msg)
        noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& i(
        std::string const& name, T const& msg) noexcept;
    template<uint32_t sz> Logger& i(char const(&msg)[sz]) noexcept;
    template<uint32_t sz> Logger& i(
        std::string const& name, char const(&msg)[sz]) noexcept;
    // d
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& d(T const& msg)
        noexcept;
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& d(
        std::string const& name, T const& msg) noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& d(T const& msg)
        noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& d(
        std::string const& name, T const& msg) noexcept;
    template<uint32_t sz> Logger& d(char const(&msg)[sz]) noexcept;
    template<uint32_t sz> Logger& d(
        std::string const& name, char const(&msg)[sz]) noexcept;
    // <<
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& operator<<(
        T const& msg) noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& operator<<(
        T const& msg) noexcept;
    template<uint32_t sz>
    Logger& operator<<(char const(&msg)[sz]) noexcept;
    // ,
    template<typename T = std::string>
    typename std::enable_if<std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& operator,(
        T const& msg) noexcept;
    template<typename T>
    typename std::enable_if<!std::is_same<std::string,
        typename std::decay<T>::type>::value, Logger>::type& operator,(
        T const& msg) noexcept;
    template<uint32_t sz>
    Logger& operator,(char const(&msg)[sz]) noexcept;
    /// Finish log
    void finish() noexcept;
protected:
    // Some global options
    static std::string defaultLogFile;
    static Logger& hasLogger(std::string const& file) noexcept;
    /**
     * Create a logger
     * @param path if path empty only for internal emptyLogger
     * @param outputs if 0 then use default
     * @param maxSize if < 0 use kDefaultLogSize, else min kMinLogSize
     * @param trunc true to trunc file, used only when path not nil and
     * Output::File set
     */
    Logger(
        std::string const& path,
        Outputs const& outputs = Outputs{},
        int32_t const maxSize = -1,
        bool const trunc = false) noexcept;
    Logger(Logger const&) = delete;
    Logger& operator=(Logger const&) = delete;
    void tryDoAcCb(
        std::string const& name,
        LogLevel const& logLevel,
        std::string const &msg) const noexcept;
    // Logger instances and related
    static Logger emptyLogger;
    static boost::shared_mutex instancesRwlock;
    static std::map<std::string, SharedPtr<Logger> > instances;
    // Instance properties
    mutable std::mutex writemutex;
    LogLevel logLevel { LogLevel::Note };
    LogLevel spinOnceLogLevel{ LogLevel::Unchange };
    FILE* log{ nullptr };
    std::string const path;
    Outputs outputs{ Output::CoutOrCerr };
    uint32_t maxSize{ kDefaultLogSize };
    bool hasIdx{ true };
    bool hasTid{ false };
    AppendCallback appendCallback{ nullptr };
    mutable boost::shared_mutex acNameFiltersRwlock;
    /// @note empty name to filter nil and empty
    std::set<std::string> acNameFilters;
};
extern std::string LogRealTime() noexcept;
inline void Logger::setDefaultLogger(std::string const& path) noexcept
{
    if (!path.empty()) {
        Logger::defaultLogFile = path;
    }
}
inline std::string Logger::getDefaultLogger() noexcept
{
    return Logger::defaultLogFile;
}
inline Logger& Logger::getFatal(
    std::string const& path, Outputs const& outputs) noexcept
{
    return Logger::getLogger(LogLevel::Fata, path, outputs);
}
inline Logger& Logger::getError(
    std::string const& path, Outputs const& outputs) noexcept
{
    return Logger::getLogger(LogLevel::Erro, path, outputs);
}
inline Logger& Logger::getWarning(
    std::string const& path, Outputs const& outputs) noexcept
{
    return Logger::getLogger(LogLevel::Warn, path, outputs);
}
inline Logger& Logger::getNote(
    std::string const& path, Outputs const& outputs) noexcept
{
    return Logger::getLogger(LogLevel::Note, path, outputs);
}
inline Logger& Logger::getInfo(
    std::string const& path, Outputs const& outputs) noexcept
{
    return Logger::getLogger(LogLevel::Info, path, outputs);
}
inline Logger& Logger::getTrace(
    std::string const& path, Outputs const& outputs) noexcept
{
    return Logger::getLogger(LogLevel::Trac, path, outputs);
}
inline Logger& Logger::getDebug(
    std::string const& path, Outputs const& outputs) noexcept
{
    return Logger::getLogger(LogLevel::Debu, path, outputs);
}
inline Logger& Logger::getDetail(
    std::string const& path, Outputs const& outputs) noexcept
{
    return Logger::getLogger(LogLevel::Deta, path, outputs);
}
inline Logger::operator bool() const noexcept
{
    return !this->path.empty();
}
inline bool Logger::isLogable(LogLevel const& ll) const noexcept
{
    return this->logLevel >= ll;
}
inline LogLevel Logger::getLogLevel() const noexcept
{
    return this->logLevel;
}
inline void Logger::setOutputs(Outputs const& o) noexcept
{
    this->outputs = o;
}
inline void Logger::setAppendCallback(AppendCallback const& ac) noexcept
{
    this->appendCallback = ac;
}
inline void Logger::enableIdx(bool const enable) noexcept
{
    this->hasIdx = enable;
}
inline void Logger::enableTid(bool const enable) noexcept
{
    this->hasTid = enable;
}
// f
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::f(
    T const& msg) noexcept
{
    this->append(nullptr, nullptr, -1, msg, LogLevel::Fata);
    return *this;
}
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::f(
    std::string const& name, T const& msg) noexcept
{
    this->append(name.c_str(), nullptr, -1, msg, LogLevel::Fata);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::f(
    T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(nullptr, nullptr, -1, ss.str(), LogLevel::Fata);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::f(
    std::string const& name, T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(name.c_str(), nullptr, -1, ss.str(), LogLevel::Fata);
    return *this;
}
template<uint32_t sz> Logger& Logger::f(char const(&msg)[sz]) noexcept
{
    this->append(nullptr, nullptr, -1, msg, LogLevel::Fata);
    return *this;
}
template<uint32_t sz> Logger& Logger::f(
    std::string const& name, char const(&msg)[sz]) noexcept
{
    this->append(name, nullptr, -1, msg, LogLevel::Fata);
    return *this;
}
// e
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::e(
    T const& msg) noexcept
{
    this->append(nullptr, nullptr, -1, msg, LogLevel::Erro);
    return *this;
}
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::e(
    std::string const& name, T const& msg) noexcept
{
    this->append(name.c_str(), nullptr, -1, msg, LogLevel::Erro);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::e(
    T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(nullptr, nullptr, -1, ss.str(), LogLevel::Erro);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::e(
    std::string const& name, T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(name.c_str(), nullptr, -1, ss.str(), LogLevel::Erro);
    return *this;
}
template<uint32_t sz> Logger& Logger::e(char const(&msg)[sz]) noexcept
{
    this->append(nullptr, nullptr, -1, msg, LogLevel::Erro);
    return *this;
}
template<uint32_t sz> Logger& Logger::e(
    std::string const& name, char const(&msg)[sz]) noexcept
{
    this->append(name, nullptr, -1, msg, LogLevel::Erro);
    return *this;
}
// w
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::w(
    T const& msg) noexcept
{
    this->append(nullptr, nullptr, -1, msg, LogLevel::Warn);
    return *this;
}
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::w(
    std::string const& name, T const& msg) noexcept
{
    this->append(name.c_str(), nullptr, -1, msg, LogLevel::Warn);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::w(
    T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(nullptr, nullptr, -1, ss.str(), LogLevel::Warn);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::w(
    std::string const& name, T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(name.c_str(), nullptr, -1, ss.str(), LogLevel::Warn);
    return *this;
}
template<uint32_t sz> Logger& Logger::w(char const(&msg)[sz]) noexcept
{
    this->append(nullptr, nullptr, -1, msg, LogLevel::Warn);
    return *this;
}
template<uint32_t sz> Logger& Logger::w(
    std::string const& name, char const(&msg)[sz]) noexcept
{
    this->append(name, nullptr, -1, msg, LogLevel::Warn);
    return *this;
}
// n
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::n(
    T const& msg) noexcept
{
    this->append(nullptr, nullptr, -1, msg, LogLevel::Note);
    return *this;
}
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::n(
    std::string const& name, T const& msg) noexcept
{
    this->append(name.c_str(), nullptr, -1, msg, LogLevel::Note);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::n(
    T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(nullptr, nullptr, -1, ss.str(), LogLevel::Note);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::n(
    std::string const& name, T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(name.c_str(), nullptr, -1, ss.str(), LogLevel::Note);
    return *this;
}
template<uint32_t sz> Logger& Logger::n(char const(&msg)[sz]) noexcept
{
    this->append(nullptr, nullptr, -1, msg, LogLevel::Note);
    return *this;
}
template<uint32_t sz> Logger& Logger::n(
    std::string const& name, char const(&msg)[sz]) noexcept
{
    this->append(name, nullptr, -1, msg, LogLevel::Note);
    return *this;
}
// i
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::i(
    T const& msg) noexcept
{
    this->append(nullptr, nullptr, -1, msg, LogLevel::Info);
    return *this;
}
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::i(
    std::string const& name, T const& msg) noexcept
{
    this->append(name.c_str(), nullptr, -1, msg, LogLevel::Info);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::i(
    T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(nullptr, nullptr, -1, ss.str(), LogLevel::Info);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::i(
    std::string const& name, T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(name.c_str(), nullptr, -1, ss.str(), LogLevel::Info);
    return *this;
}
template<uint32_t sz> Logger& Logger::i(char const(&msg)[sz]) noexcept
{
    this->append(nullptr, nullptr, -1, msg, LogLevel::Info);
    return *this;
}
template<uint32_t sz> Logger& Logger::i(
    std::string const& name, char const(&msg)[sz]) noexcept
{
    this->append(name, nullptr, -1, msg, LogLevel::Info);
    return *this;
}
// d
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::d(
    T const& msg) noexcept
{
    this->append(nullptr, nullptr, -1, msg, LogLevel::Debu);
    return *this;
}
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::d(
    std::string const& name, T const& msg) noexcept
{
    this->append(name.c_str(), nullptr, -1, msg, LogLevel::Debu);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::d(
    T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(nullptr, nullptr, -1, ss.str(), LogLevel::Debu);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::d(
    std::string const& name, T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(name.c_str(), nullptr, -1, ss.str(), LogLevel::Debu);
    return *this;
}
template<uint32_t sz> Logger& Logger::d(char const(&msg)[sz]) noexcept
{
    this->append(nullptr, nullptr, -1, msg, LogLevel::Debu);
    return *this;
}
template<uint32_t sz> Logger& Logger::d(
    std::string const& name, char const(&msg)[sz]) noexcept
{
    this->append(name, nullptr, -1, msg, LogLevel::Debu);
    return *this;
}
// <<
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::operator<<(
    T const& msg) noexcept
{
    this->append(nullptr, nullptr, -1, msg, this->logLevel);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::operator<<(
    T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(nullptr, nullptr, -1, ss.str(), this->logLevel);
    return *this;
}
template<uint32_t sz>
Logger& Logger::operator<<(char const(&msg)[sz]) noexcept
{
    this->append(nullptr, nullptr, -1, msg, this->logLevel);
    return *this;
}
template<typename T>
typename std::enable_if<std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::operator,(
    T const& msg) noexcept
{
    this->append(msg, this->logLevel);
    return *this;
}
template<typename T>
typename std::enable_if<!std::is_same<std::string,
    typename std::decay<T>::type>::value, Logger>::type& Logger::operator,(
    T const& msg) noexcept
{
    std::stringstream ss;
    ss << msg;
    this->append(ss.str(), this->logLevel);
    return *this;
}
template<uint32_t sz>
Logger& Logger::operator,(char const(&msg)[sz]) noexcept
{
    this->append(msg, this->logLevel);
    return *this;
}

console output color

console output color

#


ansi code

  • 终端字符的颜色是用 esc 开头的转义序列进行控制 是文本模式下的系统显示功能
  • esc i.e. \033 (esc ascii 码十进制 27. 八进制 33)
  • 使用 ; 分隔以连续设置
code effect
\033[0m 关闭所有属性
\033[1m 粗体
\033[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[22m 非粗体
\033[24m 非下划线
\033[25m 非闪烁
\033[27m 非反显
\033[fg-colorm e.x. \033[30m 设置前景色
\033[bg-colorm e.x. \033[47m 设置背景色
\033[nA 光标上移 n 行
\03[nB 光标下移 n 行
\033[nC 光标右移 n 行
\033[nD 光标左移 n 行
\033[y;xH 设置光标位置 (x, y)
\033[2J 清屏
\033[K 清除从光标到行尾的内容
\033[s 保存光标位置
\033[u 恢复光标位置
\033[?25l 隐藏光标
\033[?25h 显示光标

fg color

  • 字(fg)颜色: [30, 39]
value color
30
31
32 绿
33
34
35
36 深绿
37 白色

bg color

  • 背景(bg)颜色范围: [40, 49]
value color
40
41
42 绿
43
44
45
46 深绿
47 白色

example

#define YUIWONGLOGNFTALL(__name, __fmt, __args...) \
    fprintf(stdout, \
        "\033[30;49m[%s %015ld ALL ][%s] " __fmt " (%s+%d)\n\033[0m", \
        yuiwong::LogRealTime().c_str(), ::pthread_self(), __name, ##__args, \
        __FILE__, __LINE__)
#define YUIWONGLOGNFTFATA(__name, __fmt, __args...) \
    fprintf(stderr, \
        "\033[1;31;49m[%s %015ld FATA][%s] " __fmt " (%s+%d)\n\033[0m", \
        yuiwong::LogRealTime().c_str(), ::pthread_self(), __name, ##__args, \
        __FILE__, __LINE__)
#define YUIWONGLOGNFTERRO(__name, __fmt, __args...) \
    fprintf(stderr, \
        "\033[31;49m[%s %015ld ERRO][%s] " __fmt " (%s+%d)\n\033[0m", \
        yuiwong::LogRealTime().c_str(), ::pthread_self(), __name, ##__args, \
        __FILE__, __LINE__)
#define YUIWONGLOGNFTWARN(__name, __fmt, __args...) \
    fprintf(stderr, \
        "\033[33;49m[%s %015ld WARN][%s] " __fmt " (%s+%d)\n\033[0m", \
        yuiwong::LogRealTime().c_str(), ::pthread_self(), __name, ##__args, \
        __FILE__, __LINE__)
#define YUIWONGLOGNFTNOTE(__name, __fmt, __args...) \
    fprintf(stdout, \
        "\033[1;30;49m[%s %015ld NOTE][%s] " __fmt " (%s+%d)\n\033[0m", \
        yuiwong::LogRealTime().c_str(), ::pthread_self(), __name, ##__args, \
        __FILE__, __LINE__)
#define YUIWONGLOGNFTINFO(__name, __fmt, __args...) \
    fprintf(stdout, \
        "\033[30;49m[%s %015ld INFO][%s] " __fmt " (%s+%d)\n\033[0m", \
        yuiwong::LogRealTime().c_str(), ::pthread_self(), __name, ##__args, \
        __FILE__, __LINE__)
#define YUIWONGLOGNFTDEBU(__name, __fmt, __args...) \
    fprintf(stdout, \
        "\033[36;49m[%s %015ld DEBU][%s] " __fmt " (%s+%d)\n\033[0m", \
        yuiwong::LogRealTime().c_str(), ::pthread_self(), __name, ##__args, \
        __FILE__, __LINE__)
#define YUIWONGLOGNFTDETA(__name, __fmt, __args...) \
    fprintf(stdout, \
        "\033[30;49m[%s %015ld DETA][%s] " __fmt " (%s+%d)\n\033[0m", \
        yuiwong::LogRealTime().c_str(), ::pthread_self(), __name, ##__args, \
        __FILE__, __LINE__)