(root)/
freetype-2.13.2/
include/
dlg/
dlg.h
       1  // Copyright (c) 2019 nyorain
       2  // Distributed under the Boost Software License, Version 1.0.
       3  // See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt
       4  
       5  #ifndef INC_DLG_DLG_H_
       6  #define INC_DLG_DLG_H_
       7  
       8  #include <stdbool.h>
       9  #include <stddef.h>
      10  #include <stdlib.h>
      11  #include <stdarg.h>
      12  #include <stdio.h>
      13  
      14  // Hosted at https://github.com/nyorain/dlg.
      15  // There are examples and documentation.
      16  // Issue reports and contributions appreciated.
      17  
      18  // - CONFIG -
      19  // Define this macro to make all dlg macros have no effect at all
      20  // #define DLG_DISABLE
      21  
      22  // the log/assertion levels below which logs/assertions are ignored
      23  // defaulted depending on the NDEBUG macro
      24  #ifndef DLG_LOG_LEVEL
      25  	#ifdef NDEBUG
      26  		#define DLG_LOG_LEVEL dlg_level_warn
      27  	#else
      28  		#define DLG_LOG_LEVEL dlg_level_trace
      29  	#endif
      30  #endif
      31  
      32  #ifndef DLG_ASSERT_LEVEL
      33  	#ifdef NDEBUG
      34  		#define DLG_ASSERT_LEVEL dlg_level_warn
      35  	#else
      36  		#define DLG_ASSERT_LEVEL dlg_level_trace
      37  	#endif
      38  #endif
      39  
      40  // the assert level of dlg_assert
      41  #ifndef DLG_DEFAULT_ASSERT
      42  	#define DLG_DEFAULT_ASSERT dlg_level_error
      43  #endif
      44  
      45  // evaluated to the 'file' member in dlg_origin
      46  #ifndef DLG_FILE
      47  	#define DLG_FILE dlg__strip_root_path(__FILE__, DLG_BASE_PATH)
      48  
      49  	// the base path stripped from __FILE__. If you don't override DLG_FILE set this to
      50  	// the project root to make 'main.c' from '/some/bullshit/main.c'
      51  	#ifndef DLG_BASE_PATH
      52  		#define DLG_BASE_PATH ""
      53  	#endif
      54  #endif
      55  
      56  // Default tags applied to all logs/assertions (in the defining file).
      57  // Must be in format ```#define DLG_DEFAULT_TAGS "tag1", "tag2"```
      58  // or just nothing (as defaulted here)
      59  #ifndef DLG_DEFAULT_TAGS
      60  	#define DLG_DEFAULT_TAGS_TERM NULL
      61  #else
      62  	#define DLG_DEFAULT_TAGS_TERM DLG_DEFAULT_TAGS, NULL
      63  #endif
      64  
      65  // The function used for formatting. Can have any signature, but must be callable with
      66  // the arguments the log/assertions macros are called with. Must return a const char*
      67  // that will not be freed by dlg, the formatting function must keep track of it.
      68  // The formatting function might use dlg_thread_buffer or a custom owned buffer.
      69  // The returned const char* has to be valid until the dlg log/assertion ends.
      70  // Usually a c function with ... (i.e. using va_list) or a variadic c++ template do
      71  // allow formatting.
      72  #ifndef DLG_FMT_FUNC
      73  	#define DLG_FMT_FUNC dlg__printf_format
      74  #endif
      75  
      76  // Only overwrite (i.e. predefine) this if you know what you are doing.
      77  // On windows this is used to add the dllimport specified.
      78  // If you are using the static version of dlg (on windows) define
      79  // DLG_STATIC before including dlg.h
      80  #ifndef DLG_API
      81   	#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(DLG_STATIC)
      82  		#define DLG_API __declspec(dllimport)
      83  	#else
      84  		#define DLG_API
      85  	#endif
      86  #endif
      87  
      88  // This macro is used when an assertion fails. It gets the source expression
      89  // and can return an alternative (that must stay alive).
      90  // Mainly useful to execute something on failed assertion.
      91  #ifndef DLG_FAILED_ASSERTION_TEXT
      92  	#define DLG_FAILED_ASSERTION_TEXT(x) x
      93  #endif
      94  
      95  // - utility -
      96  // two methods needed since cplusplus does not support compound literals
      97  // and c does not support uniform initialization/initializer lists
      98  #ifdef __cplusplus
      99  	#include <initializer_list>
     100  	#define DLG_CREATE_TAGS(...) std::initializer_list<const char*> \
     101  		{DLG_DEFAULT_TAGS_TERM, __VA_ARGS__, NULL}.begin()
     102  #else
     103  	#define DLG_CREATE_TAGS(...) (const char* const[]) {DLG_DEFAULT_TAGS_TERM, __VA_ARGS__, NULL}
     104  #endif
     105  
     106  #ifdef __GNUC__
     107  	#define DLG_PRINTF_ATTRIB(a, b) __attribute__ ((format (printf, a, b)))
     108  #else
     109  	#define DLG_PRINTF_ATTRIB(a, b)
     110  #endif
     111  
     112  #ifdef __cplusplus
     113  extern "C" {
     114  #endif
     115  
     116  
     117  // Represents the importance of a log/assertion call.
     118  enum dlg_level {
     119  	dlg_level_trace = 0, // temporary used debug, e.g. to check if control reaches function
     120  	dlg_level_debug, // general debugging, prints e.g. all major events
     121  	dlg_level_info, // general useful information
     122  	dlg_level_warn, // warning, something went wrong but might have no (really bad) side effect
     123  	dlg_level_error, // something really went wrong; expect serious issues
     124  	dlg_level_fatal // critical error; application is likely to crash/exit
     125  };
     126  
     127  // Holds various information associated with a log/assertion call.
     128  // Forwarded to the output handler.
     129  struct dlg_origin {
     130  	const char* file;
     131  	unsigned int line;
     132  	const char* func;
     133  	enum dlg_level level;
     134  	const char** tags; // null-terminated
     135  	const char* expr; // assertion expression, otherwise null
     136  };
     137  
     138  // Type of the output handler, see dlg_set_handler.
     139  typedef void(*dlg_handler)(const struct dlg_origin* origin, const char* string, void* data);
     140  
     141  #ifndef DLG_DISABLE
     142  	// Tagged/Untagged logging with variable level
     143  	// Tags must always be in the format `("tag1", "tag2")` (including brackets)
     144  	// Example usages:
     145  	//   dlg_log(dlg_level_warning, "test 1")
     146  	//   dlg_logt(("tag1, "tag2"), dlg_level_debug, "test %d", 2)
     147  	#define dlg_log(level, ...) if(level >= DLG_LOG_LEVEL) \
     148  		dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__,  \
     149  		DLG_FMT_FUNC(__VA_ARGS__), NULL)
     150  	#define dlg_logt(level, tags, ...) if(level >= DLG_LOG_LEVEL) \
     151  		dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, __func__, \
     152  		DLG_FMT_FUNC(__VA_ARGS__), NULL)
     153  
     154  	// Dynamic level assert macros in various versions for additional arguments
     155  	// Example usages:
     156  	//   dlg_assertl(dlg_level_warning, data != nullptr);
     157  	//   dlg_assertlt(("tag1, "tag2"), dlg_level_trace, data != nullptr);
     158  	//   dlg_asserttlm(("tag1), dlg_level_warning, data != nullptr, "Data must not be null");
     159  	//   dlg_assertlm(dlg_level_error, data != nullptr, "Data must not be null");
     160  	#define dlg_assertl(level, expr) if(level >= DLG_ASSERT_LEVEL && !(expr)) \
     161  		dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__, NULL, \
     162  			DLG_FAILED_ASSERTION_TEXT(#expr))
     163  	#define dlg_assertlt(level, tags, expr) if(level >= DLG_ASSERT_LEVEL && !(expr)) \
     164  		dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__, __func__, NULL, \
     165  			DLG_FAILED_ASSERTION_TEXT(#expr))
     166  	#define dlg_assertlm(level, expr, ...) if(level >= DLG_ASSERT_LEVEL && !(expr)) \
     167  		dlg__do_log(level, DLG_CREATE_TAGS(NULL), DLG_FILE, __LINE__, __func__,  \
     168  			DLG_FMT_FUNC(__VA_ARGS__), DLG_FAILED_ASSERTION_TEXT(#expr))
     169  	#define dlg_assertltm(level, tags, expr, ...) if(level >= DLG_ASSERT_LEVEL && !(expr)) \
     170  		dlg__do_log(level, DLG_CREATE_TAGS tags, DLG_FILE, __LINE__,  \
     171  			__func__, DLG_FMT_FUNC(__VA_ARGS__), DLG_FAILED_ASSERTION_TEXT(#expr))
     172  
     173  	#define dlg__assert_or(level, tags, expr, code, msg) if(!(expr)) {\
     174  			if(level >= DLG_ASSERT_LEVEL) \
     175  				dlg__do_log(level, tags, DLG_FILE, __LINE__, __func__, msg, \
     176  					DLG_FAILED_ASSERTION_TEXT(#expr)); \
     177  			code; \
     178  		} (void) NULL
     179  
     180  	// - Private interface: not part of the abi/api but needed in macros -
     181  	// Formats the given format string and arguments as printf would, uses the thread buffer.
     182  	DLG_API const char* dlg__printf_format(const char* format, ...) DLG_PRINTF_ATTRIB(1, 2);
     183  	DLG_API void dlg__do_log(enum dlg_level lvl, const char* const*, const char*, int,
     184  		const char*, const char*, const char*);
     185  	DLG_API const char* dlg__strip_root_path(const char* file, const char* base);
     186  
     187  #else // DLG_DISABLE
     188  
     189  	#define dlg_log(level, ...)
     190  	#define dlg_logt(level, tags, ...)
     191  
     192  	#define dlg_assertl(level, expr) // assert without tags/message
     193  	#define dlg_assertlt(level, tags, expr) // assert with tags
     194  	#define dlg_assertlm(level, expr, ...) // assert with message
     195  	#define dlg_assertltm(level, tags, expr, ...) // assert with tags & message
     196  
     197  	#define dlg__assert_or(level, tags, expr, code, msg) if(!(expr)) { code; } (void) NULL
     198  #endif // DLG_DISABLE
     199  
     200  // The API below is independent from DLG_DISABLE
     201  
     202  // Sets the handler that is responsible for formatting and outputting log calls.
     203  // This function is not thread safe and the handler is set globally.
     204  // The handler itself must not change dlg tags or call a dlg macro (if it
     205  // does so, the provided string or tags array in 'origin' might get invalid).
     206  // The handler can also be used for various other things such as dealing
     207  // with failed assertions or filtering calls based on the passed tags.
     208  // The default handler is dlg_default_output (see its doc for more info).
     209  // If using c++ make sure the registered handler cannot throw e.g. by
     210  // wrapping everything into a try-catch blog.
     211  DLG_API void dlg_set_handler(dlg_handler handler, void* data);
     212  
     213  // The default output handler.
     214  // Only use this to reset the output handler, prefer to use
     215  // dlg_generic_output (from output.h) which this function simply calls.
     216  // It also flushes the stream used and correctly outputs even from multiple threads.
     217  DLG_API void dlg_default_output(const struct dlg_origin*, const char* string, void*);
     218  
     219  // Returns the currently active dlg handler and sets `data` to
     220  // its user data pointer. `data` must not be NULL.
     221  // Useful to create handler chains.
     222  // This function is not threadsafe, i.e. retrieving the handler while
     223  // changing it from another thread is unsafe.
     224  // See `dlg_set_handler`.
     225  DLG_API dlg_handler dlg_get_handler(void** data);
     226  
     227  // Adds the given tag associated with the given function to the thread specific list.
     228  // If func is not NULL the tag will only applied to calls from the same function.
     229  // Remove the tag again calling dlg_remove_tag (with exactly the same pointers!).
     230  // Does not check if the tag is already present.
     231  DLG_API void dlg_add_tag(const char* tag, const char* func);
     232  
     233  // Removes a tag added with dlg_add_tag (has no effect for tags no present).
     234  // The pointers must be exactly the same pointers that were supplied to dlg_add_tag,
     235  // this function will not check using strcmp. When the same tag/func combination
     236  // is added multiple times, this function remove exactly one candidate, it is
     237  // undefined which. Returns whether a tag was found (and removed).
     238  DLG_API bool dlg_remove_tag(const char* tag, const char* func);
     239  
     240  // Returns the thread-specific buffer and its size for dlg.
     241  // The buffer should only be used by formatting functions.
     242  // The buffer can be reallocated and the size changed, just make sure
     243  // to update both values correctly.
     244  DLG_API char** dlg_thread_buffer(size_t** size);
     245  
     246  // Untagged leveled logging
     247  #define dlg_trace(...) dlg_log(dlg_level_trace, __VA_ARGS__)
     248  #define dlg_debug(...) dlg_log(dlg_level_debug, __VA_ARGS__)
     249  #define dlg_info(...) dlg_log(dlg_level_info, __VA_ARGS__)
     250  #define dlg_warn(...) dlg_log(dlg_level_warn, __VA_ARGS__)
     251  #define dlg_error(...) dlg_log(dlg_level_error, __VA_ARGS__)
     252  #define dlg_fatal(...) dlg_log(dlg_level_fatal, __VA_ARGS__)
     253  
     254  // Tagged leveled logging
     255  #define dlg_tracet(tags, ...) dlg_logt(dlg_level_trace, tags, __VA_ARGS__)
     256  #define dlg_debugt(tags, ...) dlg_logt(dlg_level_debug, tags, __VA_ARGS__)
     257  #define dlg_infot(tags, ...) dlg_logt(dlg_level_info, tags, __VA_ARGS__)
     258  #define dlg_warnt(tags, ...) dlg_logt(dlg_level_warn, tags, __VA_ARGS__)
     259  #define dlg_errort(tags, ...) dlg_logt(dlg_level_error, tags, __VA_ARGS__)
     260  #define dlg_fatalt(tags, ...) dlg_logt(dlg_level_fatal, tags, __VA_ARGS__)
     261  
     262  // Assert macros useing DLG_DEFAULT_ASSERT as level
     263  #define dlg_assert(expr) dlg_assertl(DLG_DEFAULT_ASSERT, expr)
     264  #define dlg_assertt(tags, expr) dlg_assertlt(DLG_DEFAULT_ASSERT, tags, expr)
     265  #define dlg_assertm(expr, ...) dlg_assertlm(DLG_DEFAULT_ASSERT, expr, __VA_ARGS__)
     266  #define dlg_asserttm(tags, expr, ...) dlg_assertltm(DLG_DEFAULT_ASSERT, tags, expr, __VA_ARGS__)
     267  
     268  // If (expr) does not evaluate to true, always executes 'code' (no matter what
     269  // DLG_ASSERT_LEVEL is or if dlg is disabled or not).
     270  // When dlg is enabled and the level is greater or equal to DLG_ASSERT_LEVEL,
     271  // logs the failed assertion.
     272  // Example usages:
     273  //   dlg_assertl_or(dlg_level_warn, data != nullptr, return);
     274  //   dlg_assertlm_or(dlg_level_fatal, data != nullptr, return, "Data must not be null");
     275  //   dlg_assert_or(data != nullptr, logError(); return false);
     276  #define dlg_assertltm_or(level, tags, expr, code, ...) dlg__assert_or(level, \
     277  		DLG_CREATE_TAGS tags, expr, code, DLG_FMT_FUNC(__VA_ARGS__))
     278  #define dlg_assertlm_or(level, expr, code, ...) dlg__assert_or(level, \
     279  		DLG_CREATE_TAGS(NULL), expr, code, DLG_FMT_FUNC(__VA_ARGS__))
     280  #define dlg_assertl_or(level, expr, code) dlg__assert_or(level, \
     281  		DLG_CREATE_TAGS(NULL), expr, code, NULL)
     282  
     283  #define dlg_assert_or(expr, code) dlg_assertl_or(DLG_DEFAULT_ASSERT, expr, code)
     284  #define dlg_assertm_or(expr, code, ...) dlg_assertlm_or(DLG_DEFAULT_ASSERT, expr, code, __VA_ARGS__)
     285  
     286  #ifdef __cplusplus
     287  }
     288  #endif
     289  
     290  #endif // header guard