text: /*
   * This file is part of the EasyLogger Library.
   *
   * Copyright (c) 2015-2017, Armink, <armink.ztl@gmail.com>
   *
   * Permission is hereby granted, free of charge, to any person obtaining
   * a copy of this software and associated documentation files (the
   * 'Software'), to deal in the Software without restriction, including
   * without limitation the rights to use, copy, modify, merge, publish,
   * distribute, sublicense, and/or sell copies of the Software, and to
   * permit persons to whom the Software is furnished to do so, subject to
   * the following conditions:
   *
   * The above copyright notice and this permission notice shall be
   * included in all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
   * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
   * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
   * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
   * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   *
   * Function: It is an head file for this library. You can see all be called functions.
   * Created on: 2015-04-28
   */
  
  #ifndef __ELOG_H__
  #define __ELOG_H__
  
  #include <elog_cfg.h>
  #include <stdint.h>
  #include <stddef.h>
  #include <stdbool.h>
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /* output log's level */
  #define ELOG_LVL_ASSERT                      0
  #define ELOG_LVL_ERROR                       1
  #define ELOG_LVL_WARN                        2
  #define ELOG_LVL_INFO                        3
  #define ELOG_LVL_DEBUG                       4
  #define ELOG_LVL_VERBOSE                     5
  
  /* output log's level total number */
  #define ELOG_LVL_TOTAL_NUM                   6
  
  /* EasyLogger software version number */
  #define ELOG_SW_VERSION                      "2.0.0"
  
  /* EasyLogger assert for developer. */
  #ifdef ELOG_ASSERT_ENABLE
      #define ELOG_ASSERT(EXPR)                                                 \
      if (!(EXPR))                                                              \
      {                                                                         \
          if (elog_assert_hook == NULL) {                                       \
              elog_a("elog", "(%s) has assert failed at %s:%ld.", #EXPR, __FUNCTION__, __LINE__); \
              while (1);                                                        \
          } else {                                                              \
              elog_assert_hook(#EXPR, __FUNCTION__, __LINE__);                  \
          }                                                                     \
      }
  #else
      #define ELOG_ASSERT(EXPR)                    ((void)0);
  #endif
  
  #ifndef ELOG_OUTPUT_ENABLE
      #define elog_assert(tag, ...)
      #define elog_error(tag, ...)
      #define elog_warn(tag, ...)
      #define elog_info(tag, ...)
      #define elog_debug(tag, ...)
      #define elog_verbose(tag, ...)
  #else /* ELOG_OUTPUT_ENABLE */
      #if ELOG_OUTPUT_LVL >= ELOG_LVL_ASSERT
          #define elog_assert(tag, ...) \
                  elog_output(ELOG_LVL_ASSERT, tag, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
      #else
          #define elog_assert(tag, ...)
      #endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_ASSERT */
  
      #if ELOG_OUTPUT_LVL >= ELOG_LVL_ERROR
          #define elog_error(tag, ...) \
                  elog_output(ELOG_LVL_ERROR, tag, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
      #else
          #define elog_error(tag, ...)
      #endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_ERROR */
  
      #if ELOG_OUTPUT_LVL >= ELOG_LVL_WARN
          #define elog_warn(tag, ...) \
                  elog_output(ELOG_LVL_WARN, tag, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
      #else
          #define elog_warn(tag, ...)
      #endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_WARN */
  
      #if ELOG_OUTPUT_LVL >= ELOG_LVL_INFO
          #define elog_info(tag, ...) \
                  elog_output(ELOG_LVL_INFO, tag, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
      #else
          #define elog_info(tag, ...)
      #endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_INFO */
  
      #if ELOG_OUTPUT_LVL >= ELOG_LVL_DEBUG
          #define elog_debug(tag, ...) \
                  elog_output(ELOG_LVL_DEBUG, tag, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
      #else
          #define elog_debug(tag, ...)
      #endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_DEBUG */
  
      #if ELOG_OUTPUT_LVL == ELOG_LVL_VERBOSE
          #define elog_verbose(tag, ...) \
                  elog_output(ELOG_LVL_VERBOSE, tag, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
      #else
          #define elog_verbose(tag, ...)
      #endif /* ELOG_OUTPUT_LVL == ELOG_LVL_VERBOSE */
  #endif /* ELOG_OUTPUT_ENABLE */
  
  /* all formats index */
  typedef enum {
      ELOG_FMT_LVL    = 1 << 0, /**< level */
      ELOG_FMT_TAG    = 1 << 1, /**< tag */
      ELOG_FMT_TIME   = 1 << 2, /**< current time */
      ELOG_FMT_P_INFO = 1 << 3, /**< process info */
      ELOG_FMT_T_INFO = 1 << 4, /**< thread info */
      ELOG_FMT_DIR    = 1 << 5, /**< file directory and name */
      ELOG_FMT_FUNC   = 1 << 6, /**< function name */
      ELOG_FMT_LINE   = 1 << 7, /**< line number */
  } ElogFmtIndex;
  
  /* macro definition for all formats */
  #define ELOG_FMT_ALL    (ELOG_FMT_LVL|ELOG_FMT_TAG|ELOG_FMT_TIME|ELOG_FMT_P_INFO|ELOG_FMT_T_INFO| \
      ELOG_FMT_DIR|ELOG_FMT_FUNC|ELOG_FMT_LINE)
  
  /* output log's filter */
  typedef struct {
      uint8_t level;
      char tag[ELOG_FILTER_TAG_MAX_LEN + 1];
      char keyword[ELOG_FILTER_KW_MAX_LEN + 1];
  } ElogFilter, *ElogFilter_t;
  
  /* easy logger */
  typedef struct {
      ElogFilter filter;
      size_t enabled_fmt_set[ELOG_LVL_TOTAL_NUM];
      bool output_enabled;
      bool output_lock_enabled;
      bool output_is_locked_before_enable;
      bool output_is_locked_before_disable;
      bool text_print_enabled; //2018.12.16 -by zhsun
  
  #ifdef ELOG_COLOR_ENABLE
      bool text_color_enabled;
  #endif
  
  }EasyLogger, *EasyLogger_t;
  
  /* EasyLogger error code */
  typedef enum {
      ELOG_NO_ERR,
      ELOG_SOCKET_ERR,
  } ElogErrCode;
  
  /* elog.c */
  /* level output info */
  extern const char *level_output_info[6];
  #ifdef ELOG_COLOR_ENABLE
  /* color output info */
  #ifdef __LINUX__
  extern const char *color_output_info[6];
  #endif /* __LINUX__ */
  #ifdef __WIN32__
  extern const WORD color_output_info[];
  #endif /* __WIN32__ */
  #endif /* ELOG_COLOR_ENABLE */
  
  ElogErrCode elog_init(void);
  void elog_start(void);
  void elog_set_output_enabled(bool enabled);
  bool elog_get_output_enabled(void);
  void elog_set_text_color_enabled(bool enabled);
  bool elog_get_text_color_enabled(void);
  void elog_set_fmt(uint8_t level, size_t set);
  void elog_set_filter(uint8_t level, const char *tag, const char *keyword);
  void elog_set_filter_lvl(uint8_t level);
  uint8_t elog_get_filter_lvl(void);
  void elog_set_filter_tag(const char *tag);
  void elog_set_filter_kw(const char *keyword);
  char* elog_get_filter_kw();
  void elog_raw(const char *format, ...);
  void elog_output(uint8_t level, const char *tag, const char *file, const char *func,
          const long line, const char *format, ...);
  void elog_output_lock_enabled(bool enabled);
  extern void (*elog_assert_hook)(const char* expr, const char* func, size_t line);
  void elog_assert_set_hook(void (*hook)(const char* expr, const char* func, size_t line));
  int8_t elog_find_lvl(const char *log);
  const char *elog_find_tag(const char *log, uint8_t lvl, size_t *tag_len);
  void elog_hexdump(const char *name, uint8_t width, uint8_t *buf, uint16_t size);
  //2018.12.26 -by zhsun
  void elog_set_text_print_enabled(bool enabled);
  bool elog_get_text_print_enabled(void);
  bool elog_set_logserver_ip(const char *ipaddr);
  
  #define elog_a(tag, ...)     elog_assert(tag, __VA_ARGS__)
  #define elog_e(tag, ...)     elog_error(tag, __VA_ARGS__)
  #define elog_w(tag, ...)     elog_warn(tag, __VA_ARGS__)
  #define elog_i(tag, ...)     elog_info(tag, __VA_ARGS__)
  #define elog_d(tag, ...)     elog_debug(tag, __VA_ARGS__)
  #define elog_v(tag, ...)     elog_verbose(tag, __VA_ARGS__)
  
  /**
   * log API short definition
   * NOTE: The `LOG_TAG` and `LOG_LVL` must defined before including the <elog.h> when you want to use log_x API.
   */
  #if !defined(LOG_TAG)
      #define LOG_TAG          "NO_TAG"
  #endif
  #if !defined(LOG_LVL)
      #define LOG_LVL          ELOG_LVL_VERBOSE
  #endif
  #if LOG_LVL >= ELOG_LVL_ASSERT
      #define log_a(...)       elog_a(LOG_TAG, __VA_ARGS__)
  #else
      #define log_a(...)       ((void)0);
  #endif
  #if LOG_LVL >= ELOG_LVL_ERROR
      #define log_e(...)       elog_e(LOG_TAG, __VA_ARGS__)
  #else
      #define log_e(...)       ((void)0);
  #endif
  #if LOG_LVL >= ELOG_LVL_WARN
      #define log_w(...)       elog_w(LOG_TAG, __VA_ARGS__)
  #else
      #define log_w(...)       ((void)0);
  #endif
  #if LOG_LVL >= ELOG_LVL_INFO
      #define log_i(...)       elog_i(LOG_TAG, __VA_ARGS__)
  #else
      #define log_i(...)       ((void)0);
  #endif
  #if LOG_LVL >= ELOG_LVL_DEBUG
      #define log_d(...)       elog_d(LOG_TAG, __VA_ARGS__)
  #else
      #define log_d(...)       ((void)0);
  #endif
  #if LOG_LVL >= ELOG_LVL_VERBOSE
      #define log_v(...)       elog_v(LOG_TAG, __VA_ARGS__)
  #else
      #define log_v(...)       ((void)0);
  #endif
  
  /* assert API short definition */
  #if !defined(assert)
      #define assert           ELOG_ASSERT
  #endif
  
  /* elog_buf.c */
  void elog_buf_enabled(bool enabled);
  void elog_flush(void);
  
  /* elog_async.c */
  void elog_async_enabled(bool enabled);
  size_t elog_async_get_log(char *log, size_t size);
  size_t elog_async_get_line_log(char *log, size_t size);
  
  /* elog_utils.c */
  size_t elog_strcpy(size_t cur_len, char *dst, const char *src);
  size_t elog_cpyln(char *line, const char *log, size_t len);
  void *elog_memcpy(void *dst, const void *src, size_t count);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* __ELOG_H__ */
  