1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright © 2017  Google, Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci *  This is part of HarfBuzz, a text shaping library.
5cb93a386Sopenharmony_ci *
6cb93a386Sopenharmony_ci * Permission is hereby granted, without written agreement and without
7cb93a386Sopenharmony_ci * license or royalty fees, to use, copy, modify, and distribute this
8cb93a386Sopenharmony_ci * software and its documentation for any purpose, provided that the
9cb93a386Sopenharmony_ci * above copyright notice and the following two paragraphs appear in
10cb93a386Sopenharmony_ci * all copies of this software.
11cb93a386Sopenharmony_ci *
12cb93a386Sopenharmony_ci * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13cb93a386Sopenharmony_ci * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14cb93a386Sopenharmony_ci * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15cb93a386Sopenharmony_ci * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16cb93a386Sopenharmony_ci * DAMAGE.
17cb93a386Sopenharmony_ci *
18cb93a386Sopenharmony_ci * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19cb93a386Sopenharmony_ci * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20cb93a386Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21cb93a386Sopenharmony_ci * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22cb93a386Sopenharmony_ci * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23cb93a386Sopenharmony_ci *
24cb93a386Sopenharmony_ci * Google Author(s): Behdad Esfahbod
25cb93a386Sopenharmony_ci */
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_ci#ifndef HB_DEBUG_HH
28cb93a386Sopenharmony_ci#define HB_DEBUG_HH
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ci#include "hb.hh"
31cb93a386Sopenharmony_ci#include "hb-atomic.hh"
32cb93a386Sopenharmony_ci#include "hb-algs.hh"
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_ci#ifndef HB_DEBUG
36cb93a386Sopenharmony_ci#define HB_DEBUG 0
37cb93a386Sopenharmony_ci#endif
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_ci/*
41cb93a386Sopenharmony_ci * Global runtime options.
42cb93a386Sopenharmony_ci */
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_cistruct hb_options_t
45cb93a386Sopenharmony_ci{
46cb93a386Sopenharmony_ci  bool unused : 1; /* In-case sign bit is here. */
47cb93a386Sopenharmony_ci  bool initialized : 1;
48cb93a386Sopenharmony_ci  bool uniscribe_bug_compatible : 1;
49cb93a386Sopenharmony_ci};
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ciunion hb_options_union_t {
52cb93a386Sopenharmony_ci  int i;
53cb93a386Sopenharmony_ci  hb_options_t opts;
54cb93a386Sopenharmony_ci};
55cb93a386Sopenharmony_cistatic_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), "");
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ciHB_INTERNAL void
58cb93a386Sopenharmony_ci_hb_options_init ();
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_ciextern HB_INTERNAL hb_atomic_int_t _hb_options;
61cb93a386Sopenharmony_ci
62cb93a386Sopenharmony_cistatic inline hb_options_t
63cb93a386Sopenharmony_cihb_options ()
64cb93a386Sopenharmony_ci{
65cb93a386Sopenharmony_ci#ifdef HB_NO_GETENV
66cb93a386Sopenharmony_ci  return hb_options_t ();
67cb93a386Sopenharmony_ci#endif
68cb93a386Sopenharmony_ci  /* Make a local copy, so we can access bitfield threadsafely. */
69cb93a386Sopenharmony_ci  hb_options_union_t u;
70cb93a386Sopenharmony_ci  u.i = _hb_options.get_relaxed ();
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_ci  if (unlikely (!u.i))
73cb93a386Sopenharmony_ci  {
74cb93a386Sopenharmony_ci    _hb_options_init ();
75cb93a386Sopenharmony_ci    u.i = _hb_options.get_relaxed ();
76cb93a386Sopenharmony_ci  }
77cb93a386Sopenharmony_ci
78cb93a386Sopenharmony_ci  return u.opts;
79cb93a386Sopenharmony_ci}
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci
82cb93a386Sopenharmony_ci/*
83cb93a386Sopenharmony_ci * Debug output (needs enabling at compile time.)
84cb93a386Sopenharmony_ci */
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_cistatic inline bool
87cb93a386Sopenharmony_ci_hb_debug (unsigned int level,
88cb93a386Sopenharmony_ci	   unsigned int max_level)
89cb93a386Sopenharmony_ci{
90cb93a386Sopenharmony_ci  return level < max_level;
91cb93a386Sopenharmony_ci}
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci#define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT))
94cb93a386Sopenharmony_ci#define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0))
95cb93a386Sopenharmony_ci
96cb93a386Sopenharmony_cistatic inline void
97cb93a386Sopenharmony_ci_hb_print_func (const char *func)
98cb93a386Sopenharmony_ci{
99cb93a386Sopenharmony_ci  if (func)
100cb93a386Sopenharmony_ci  {
101cb93a386Sopenharmony_ci    unsigned int func_len = strlen (func);
102cb93a386Sopenharmony_ci    /* Skip "static" */
103cb93a386Sopenharmony_ci    if (0 == strncmp (func, "static ", 7))
104cb93a386Sopenharmony_ci      func += 7;
105cb93a386Sopenharmony_ci    /* Skip "typename" */
106cb93a386Sopenharmony_ci    if (0 == strncmp (func, "typename ", 9))
107cb93a386Sopenharmony_ci      func += 9;
108cb93a386Sopenharmony_ci    /* Skip return type */
109cb93a386Sopenharmony_ci    const char *space = strchr (func, ' ');
110cb93a386Sopenharmony_ci    if (space)
111cb93a386Sopenharmony_ci      func = space + 1;
112cb93a386Sopenharmony_ci    /* Skip parameter list */
113cb93a386Sopenharmony_ci    const char *paren = strchr (func, '(');
114cb93a386Sopenharmony_ci    if (paren)
115cb93a386Sopenharmony_ci      func_len = paren - func;
116cb93a386Sopenharmony_ci    fprintf (stderr, "%.*s", func_len, func);
117cb93a386Sopenharmony_ci  }
118cb93a386Sopenharmony_ci}
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_citemplate <int max_level> static inline void
121cb93a386Sopenharmony_ci_hb_debug_msg_va (const char *what,
122cb93a386Sopenharmony_ci		  const void *obj,
123cb93a386Sopenharmony_ci		  const char *func,
124cb93a386Sopenharmony_ci		  bool indented,
125cb93a386Sopenharmony_ci		  unsigned int level,
126cb93a386Sopenharmony_ci		  int level_dir,
127cb93a386Sopenharmony_ci		  const char *message,
128cb93a386Sopenharmony_ci		  va_list ap) HB_PRINTF_FUNC(7, 0);
129cb93a386Sopenharmony_citemplate <int max_level> static inline void
130cb93a386Sopenharmony_ci_hb_debug_msg_va (const char *what,
131cb93a386Sopenharmony_ci		  const void *obj,
132cb93a386Sopenharmony_ci		  const char *func,
133cb93a386Sopenharmony_ci		  bool indented,
134cb93a386Sopenharmony_ci		  unsigned int level,
135cb93a386Sopenharmony_ci		  int level_dir,
136cb93a386Sopenharmony_ci		  const char *message,
137cb93a386Sopenharmony_ci		  va_list ap)
138cb93a386Sopenharmony_ci{
139cb93a386Sopenharmony_ci  if (!_hb_debug (level, max_level))
140cb93a386Sopenharmony_ci    return;
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ci  fprintf (stderr, "%-10s", what ? what : "");
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_ci  if (obj)
145cb93a386Sopenharmony_ci    fprintf (stderr, "(%*p) ", (unsigned int) (2 * sizeof (void *)), obj);
146cb93a386Sopenharmony_ci  else
147cb93a386Sopenharmony_ci    fprintf (stderr, " %*s  ", (unsigned int) (2 * sizeof (void *)), "");
148cb93a386Sopenharmony_ci
149cb93a386Sopenharmony_ci  if (indented) {
150cb93a386Sopenharmony_ci#define VBAR	"\342\224\202"	/* U+2502 BOX DRAWINGS LIGHT VERTICAL */
151cb93a386Sopenharmony_ci#define VRBAR	"\342\224\234"	/* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
152cb93a386Sopenharmony_ci#define DLBAR	"\342\225\256"	/* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */
153cb93a386Sopenharmony_ci#define ULBAR	"\342\225\257"	/* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */
154cb93a386Sopenharmony_ci#define LBAR	"\342\225\264"	/* U+2574 BOX DRAWINGS LIGHT LEFT */
155cb93a386Sopenharmony_ci    static const char bars[] =
156cb93a386Sopenharmony_ci      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
157cb93a386Sopenharmony_ci      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
158cb93a386Sopenharmony_ci      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
159cb93a386Sopenharmony_ci      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
160cb93a386Sopenharmony_ci      VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
161cb93a386Sopenharmony_ci    fprintf (stderr, "%2u %s" VRBAR "%s",
162cb93a386Sopenharmony_ci	     level,
163cb93a386Sopenharmony_ci	     bars + sizeof (bars) - 1 - hb_min ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
164cb93a386Sopenharmony_ci	     level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
165cb93a386Sopenharmony_ci  } else
166cb93a386Sopenharmony_ci    fprintf (stderr, "   " VRBAR LBAR);
167cb93a386Sopenharmony_ci
168cb93a386Sopenharmony_ci  _hb_print_func (func);
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_ci  if (message)
171cb93a386Sopenharmony_ci  {
172cb93a386Sopenharmony_ci    fprintf (stderr, ": ");
173cb93a386Sopenharmony_ci    vfprintf (stderr, message, ap);
174cb93a386Sopenharmony_ci  }
175cb93a386Sopenharmony_ci
176cb93a386Sopenharmony_ci  fprintf (stderr, "\n");
177cb93a386Sopenharmony_ci}
178cb93a386Sopenharmony_citemplate <> inline void HB_PRINTF_FUNC(7, 0)
179cb93a386Sopenharmony_ci_hb_debug_msg_va<0> (const char *what HB_UNUSED,
180cb93a386Sopenharmony_ci		     const void *obj HB_UNUSED,
181cb93a386Sopenharmony_ci		     const char *func HB_UNUSED,
182cb93a386Sopenharmony_ci		     bool indented HB_UNUSED,
183cb93a386Sopenharmony_ci		     unsigned int level HB_UNUSED,
184cb93a386Sopenharmony_ci		     int level_dir HB_UNUSED,
185cb93a386Sopenharmony_ci		     const char *message HB_UNUSED,
186cb93a386Sopenharmony_ci		     va_list ap HB_UNUSED) {}
187cb93a386Sopenharmony_ci
188cb93a386Sopenharmony_citemplate <int max_level> static inline void
189cb93a386Sopenharmony_ci_hb_debug_msg (const char *what,
190cb93a386Sopenharmony_ci	       const void *obj,
191cb93a386Sopenharmony_ci	       const char *func,
192cb93a386Sopenharmony_ci	       bool indented,
193cb93a386Sopenharmony_ci	       unsigned int level,
194cb93a386Sopenharmony_ci	       int level_dir,
195cb93a386Sopenharmony_ci	       const char *message,
196cb93a386Sopenharmony_ci	       ...) HB_PRINTF_FUNC(7, 8);
197cb93a386Sopenharmony_citemplate <int max_level> static inline void HB_PRINTF_FUNC(7, 8)
198cb93a386Sopenharmony_ci_hb_debug_msg (const char *what,
199cb93a386Sopenharmony_ci	       const void *obj,
200cb93a386Sopenharmony_ci	       const char *func,
201cb93a386Sopenharmony_ci	       bool indented,
202cb93a386Sopenharmony_ci	       unsigned int level,
203cb93a386Sopenharmony_ci	       int level_dir,
204cb93a386Sopenharmony_ci	       const char *message,
205cb93a386Sopenharmony_ci	       ...)
206cb93a386Sopenharmony_ci{
207cb93a386Sopenharmony_ci  va_list ap;
208cb93a386Sopenharmony_ci  va_start (ap, message);
209cb93a386Sopenharmony_ci  _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap);
210cb93a386Sopenharmony_ci  va_end (ap);
211cb93a386Sopenharmony_ci}
212cb93a386Sopenharmony_citemplate <> inline void
213cb93a386Sopenharmony_ci_hb_debug_msg<0> (const char *what HB_UNUSED,
214cb93a386Sopenharmony_ci		  const void *obj HB_UNUSED,
215cb93a386Sopenharmony_ci		  const char *func HB_UNUSED,
216cb93a386Sopenharmony_ci		  bool indented HB_UNUSED,
217cb93a386Sopenharmony_ci		  unsigned int level HB_UNUSED,
218cb93a386Sopenharmony_ci		  int level_dir HB_UNUSED,
219cb93a386Sopenharmony_ci		  const char *message HB_UNUSED,
220cb93a386Sopenharmony_ci		  ...) HB_PRINTF_FUNC(7, 8);
221cb93a386Sopenharmony_citemplate <> inline void HB_PRINTF_FUNC(7, 8)
222cb93a386Sopenharmony_ci_hb_debug_msg<0> (const char *what HB_UNUSED,
223cb93a386Sopenharmony_ci		  const void *obj HB_UNUSED,
224cb93a386Sopenharmony_ci		  const char *func HB_UNUSED,
225cb93a386Sopenharmony_ci		  bool indented HB_UNUSED,
226cb93a386Sopenharmony_ci		  unsigned int level HB_UNUSED,
227cb93a386Sopenharmony_ci		  int level_dir HB_UNUSED,
228cb93a386Sopenharmony_ci		  const char *message HB_UNUSED,
229cb93a386Sopenharmony_ci		  ...) {}
230cb93a386Sopenharmony_ci
231cb93a386Sopenharmony_ci#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...)	_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr,    true, (LEVEL), (LEVEL_DIR), __VA_ARGS__)
232cb93a386Sopenharmony_ci#define DEBUG_MSG(WHAT, OBJ, ...)				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr,    false, 0, 0, __VA_ARGS__)
233cb93a386Sopenharmony_ci#define DEBUG_MSG_FUNC(WHAT, OBJ, ...)				_hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__)
234cb93a386Sopenharmony_ci
235cb93a386Sopenharmony_ci
236cb93a386Sopenharmony_ci/*
237cb93a386Sopenharmony_ci * Printer
238cb93a386Sopenharmony_ci */
239cb93a386Sopenharmony_ci
240cb93a386Sopenharmony_citemplate <typename T>
241cb93a386Sopenharmony_cistruct hb_printer_t {
242cb93a386Sopenharmony_ci  const char *print (const T&) { return "something"; }
243cb93a386Sopenharmony_ci};
244cb93a386Sopenharmony_ci
245cb93a386Sopenharmony_citemplate <>
246cb93a386Sopenharmony_cistruct hb_printer_t<bool> {
247cb93a386Sopenharmony_ci  const char *print (bool v) { return v ? "true" : "false"; }
248cb93a386Sopenharmony_ci};
249cb93a386Sopenharmony_ci
250cb93a386Sopenharmony_citemplate <>
251cb93a386Sopenharmony_cistruct hb_printer_t<hb_empty_t> {
252cb93a386Sopenharmony_ci  const char *print (hb_empty_t) { return ""; }
253cb93a386Sopenharmony_ci};
254cb93a386Sopenharmony_ci
255cb93a386Sopenharmony_ci
256cb93a386Sopenharmony_ci/*
257cb93a386Sopenharmony_ci * Trace
258cb93a386Sopenharmony_ci */
259cb93a386Sopenharmony_ci
260cb93a386Sopenharmony_citemplate <typename T>
261cb93a386Sopenharmony_cistatic inline void _hb_warn_no_return (bool returned)
262cb93a386Sopenharmony_ci{
263cb93a386Sopenharmony_ci  if (unlikely (!returned)) {
264cb93a386Sopenharmony_ci    fprintf (stderr, "OUCH, returned with no call to return_trace().  This is a bug, please report.\n");
265cb93a386Sopenharmony_ci  }
266cb93a386Sopenharmony_ci}
267cb93a386Sopenharmony_citemplate <>
268cb93a386Sopenharmony_ci/*static*/ inline void _hb_warn_no_return<hb_empty_t> (bool returned HB_UNUSED)
269cb93a386Sopenharmony_ci{}
270cb93a386Sopenharmony_ci
271cb93a386Sopenharmony_citemplate <int max_level, typename ret_t>
272cb93a386Sopenharmony_cistruct hb_auto_trace_t
273cb93a386Sopenharmony_ci{
274cb93a386Sopenharmony_ci  explicit inline hb_auto_trace_t (unsigned int *plevel_,
275cb93a386Sopenharmony_ci				   const char *what_,
276cb93a386Sopenharmony_ci				   const void *obj_,
277cb93a386Sopenharmony_ci				   const char *func,
278cb93a386Sopenharmony_ci				   const char *message,
279cb93a386Sopenharmony_ci				   ...) HB_PRINTF_FUNC(6, 7)
280cb93a386Sopenharmony_ci				   : plevel (plevel_), what (what_), obj (obj_), returned (false)
281cb93a386Sopenharmony_ci  {
282cb93a386Sopenharmony_ci    if (plevel) ++*plevel;
283cb93a386Sopenharmony_ci
284cb93a386Sopenharmony_ci    va_list ap;
285cb93a386Sopenharmony_ci    va_start (ap, message);
286cb93a386Sopenharmony_ci    _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
287cb93a386Sopenharmony_ci    va_end (ap);
288cb93a386Sopenharmony_ci  }
289cb93a386Sopenharmony_ci  ~hb_auto_trace_t ()
290cb93a386Sopenharmony_ci  {
291cb93a386Sopenharmony_ci    _hb_warn_no_return<ret_t> (returned);
292cb93a386Sopenharmony_ci    if (!returned) {
293cb93a386Sopenharmony_ci      _hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1, " ");
294cb93a386Sopenharmony_ci    }
295cb93a386Sopenharmony_ci    if (plevel) --*plevel;
296cb93a386Sopenharmony_ci  }
297cb93a386Sopenharmony_ci
298cb93a386Sopenharmony_ci  template <typename T>
299cb93a386Sopenharmony_ci  T ret (T&& v,
300cb93a386Sopenharmony_ci	 const char *func = "",
301cb93a386Sopenharmony_ci	 unsigned int line = 0)
302cb93a386Sopenharmony_ci  {
303cb93a386Sopenharmony_ci    if (unlikely (returned)) {
304cb93a386Sopenharmony_ci      fprintf (stderr, "OUCH, double calls to return_trace().  This is a bug, please report.\n");
305cb93a386Sopenharmony_ci      return std::forward<T> (v);
306cb93a386Sopenharmony_ci    }
307cb93a386Sopenharmony_ci
308cb93a386Sopenharmony_ci    _hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
309cb93a386Sopenharmony_ci			      "return %s (line %d)",
310cb93a386Sopenharmony_ci			      hb_printer_t<hb_decay<decltype (v)>>().print (v), line);
311cb93a386Sopenharmony_ci    if (plevel) --*plevel;
312cb93a386Sopenharmony_ci    plevel = nullptr;
313cb93a386Sopenharmony_ci    returned = true;
314cb93a386Sopenharmony_ci    return std::forward<T> (v);
315cb93a386Sopenharmony_ci  }
316cb93a386Sopenharmony_ci
317cb93a386Sopenharmony_ci  private:
318cb93a386Sopenharmony_ci  unsigned int *plevel;
319cb93a386Sopenharmony_ci  const char *what;
320cb93a386Sopenharmony_ci  const void *obj;
321cb93a386Sopenharmony_ci  bool returned;
322cb93a386Sopenharmony_ci};
323cb93a386Sopenharmony_citemplate <typename ret_t> /* Make sure we don't use hb_auto_trace_t when not tracing. */
324cb93a386Sopenharmony_cistruct hb_auto_trace_t<0, ret_t>
325cb93a386Sopenharmony_ci{
326cb93a386Sopenharmony_ci  explicit inline hb_auto_trace_t (unsigned int *plevel_,
327cb93a386Sopenharmony_ci				   const char *what_,
328cb93a386Sopenharmony_ci				   const void *obj_,
329cb93a386Sopenharmony_ci				   const char *func,
330cb93a386Sopenharmony_ci				   const char *message,
331cb93a386Sopenharmony_ci				   ...) HB_PRINTF_FUNC(6, 7) {}
332cb93a386Sopenharmony_ci
333cb93a386Sopenharmony_ci  template <typename T>
334cb93a386Sopenharmony_ci  T ret (T&& v,
335cb93a386Sopenharmony_ci	 const char *func HB_UNUSED = nullptr,
336cb93a386Sopenharmony_ci	 unsigned int line HB_UNUSED = 0) { return std::forward<T> (v); }
337cb93a386Sopenharmony_ci};
338cb93a386Sopenharmony_ci
339cb93a386Sopenharmony_ci/* For disabled tracing; optimize out everything.
340cb93a386Sopenharmony_ci * https://github.com/harfbuzz/harfbuzz/pull/605 */
341cb93a386Sopenharmony_citemplate <typename ret_t>
342cb93a386Sopenharmony_cistruct hb_no_trace_t {
343cb93a386Sopenharmony_ci  template <typename T>
344cb93a386Sopenharmony_ci  T ret (T&& v,
345cb93a386Sopenharmony_ci	 const char *func HB_UNUSED = nullptr,
346cb93a386Sopenharmony_ci	 unsigned int line HB_UNUSED = 0) { return std::forward<T> (v); }
347cb93a386Sopenharmony_ci};
348cb93a386Sopenharmony_ci
349cb93a386Sopenharmony_ci#define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__)
350cb93a386Sopenharmony_ci
351cb93a386Sopenharmony_ci
352cb93a386Sopenharmony_ci/*
353cb93a386Sopenharmony_ci * Instances.
354cb93a386Sopenharmony_ci */
355cb93a386Sopenharmony_ci
356cb93a386Sopenharmony_ci#ifndef HB_DEBUG_ARABIC
357cb93a386Sopenharmony_ci#define HB_DEBUG_ARABIC (HB_DEBUG+0)
358cb93a386Sopenharmony_ci#endif
359cb93a386Sopenharmony_ci
360cb93a386Sopenharmony_ci#ifndef HB_DEBUG_BLOB
361cb93a386Sopenharmony_ci#define HB_DEBUG_BLOB (HB_DEBUG+0)
362cb93a386Sopenharmony_ci#endif
363cb93a386Sopenharmony_ci
364cb93a386Sopenharmony_ci#ifndef HB_DEBUG_CORETEXT
365cb93a386Sopenharmony_ci#define HB_DEBUG_CORETEXT (HB_DEBUG+0)
366cb93a386Sopenharmony_ci#endif
367cb93a386Sopenharmony_ci
368cb93a386Sopenharmony_ci#ifndef HB_DEBUG_DIRECTWRITE
369cb93a386Sopenharmony_ci#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0)
370cb93a386Sopenharmony_ci#endif
371cb93a386Sopenharmony_ci
372cb93a386Sopenharmony_ci#ifndef HB_DEBUG_FT
373cb93a386Sopenharmony_ci#define HB_DEBUG_FT (HB_DEBUG+0)
374cb93a386Sopenharmony_ci#endif
375cb93a386Sopenharmony_ci
376cb93a386Sopenharmony_ci#ifndef HB_DEBUG_OBJECT
377cb93a386Sopenharmony_ci#define HB_DEBUG_OBJECT (HB_DEBUG+0)
378cb93a386Sopenharmony_ci#endif
379cb93a386Sopenharmony_ci
380cb93a386Sopenharmony_ci#ifndef HB_DEBUG_SHAPE_PLAN
381cb93a386Sopenharmony_ci#define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0)
382cb93a386Sopenharmony_ci#endif
383cb93a386Sopenharmony_ci
384cb93a386Sopenharmony_ci#ifndef HB_DEBUG_UNISCRIBE
385cb93a386Sopenharmony_ci#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
386cb93a386Sopenharmony_ci#endif
387cb93a386Sopenharmony_ci
388cb93a386Sopenharmony_ci/*
389cb93a386Sopenharmony_ci * With tracing.
390cb93a386Sopenharmony_ci */
391cb93a386Sopenharmony_ci
392cb93a386Sopenharmony_ci#ifndef HB_DEBUG_APPLY
393cb93a386Sopenharmony_ci#define HB_DEBUG_APPLY (HB_DEBUG+0)
394cb93a386Sopenharmony_ci#endif
395cb93a386Sopenharmony_ci#if HB_DEBUG_APPLY
396cb93a386Sopenharmony_ci#define TRACE_APPLY(this) \
397cb93a386Sopenharmony_ci	hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
398cb93a386Sopenharmony_ci	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
399cb93a386Sopenharmony_ci	 "idx %d gid %u lookup %d", \
400cb93a386Sopenharmony_ci	 c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index)
401cb93a386Sopenharmony_ci#else
402cb93a386Sopenharmony_ci#define TRACE_APPLY(this) hb_no_trace_t<bool> trace
403cb93a386Sopenharmony_ci#endif
404cb93a386Sopenharmony_ci
405cb93a386Sopenharmony_ci#ifndef HB_DEBUG_SANITIZE
406cb93a386Sopenharmony_ci#define HB_DEBUG_SANITIZE (HB_DEBUG+0)
407cb93a386Sopenharmony_ci#endif
408cb93a386Sopenharmony_ci#if HB_DEBUG_SANITIZE
409cb93a386Sopenharmony_ci#define TRACE_SANITIZE(this) \
410cb93a386Sopenharmony_ci	hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \
411cb93a386Sopenharmony_ci	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
412cb93a386Sopenharmony_ci	 " ")
413cb93a386Sopenharmony_ci#else
414cb93a386Sopenharmony_ci#define TRACE_SANITIZE(this) hb_no_trace_t<bool> trace
415cb93a386Sopenharmony_ci#endif
416cb93a386Sopenharmony_ci
417cb93a386Sopenharmony_ci#ifndef HB_DEBUG_SERIALIZE
418cb93a386Sopenharmony_ci#define HB_DEBUG_SERIALIZE (HB_DEBUG+0)
419cb93a386Sopenharmony_ci#endif
420cb93a386Sopenharmony_ci#if HB_DEBUG_SERIALIZE
421cb93a386Sopenharmony_ci#define TRACE_SERIALIZE(this) \
422cb93a386Sopenharmony_ci	hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \
423cb93a386Sopenharmony_ci	(&c->debug_depth, "SERIALIZE", c, HB_FUNC, \
424cb93a386Sopenharmony_ci	 " ")
425cb93a386Sopenharmony_ci#else
426cb93a386Sopenharmony_ci#define TRACE_SERIALIZE(this) hb_no_trace_t<bool> trace
427cb93a386Sopenharmony_ci#endif
428cb93a386Sopenharmony_ci
429cb93a386Sopenharmony_ci#ifndef HB_DEBUG_SUBSET
430cb93a386Sopenharmony_ci#define HB_DEBUG_SUBSET (HB_DEBUG+0)
431cb93a386Sopenharmony_ci#endif
432cb93a386Sopenharmony_ci#if HB_DEBUG_SUBSET
433cb93a386Sopenharmony_ci#define TRACE_SUBSET(this) \
434cb93a386Sopenharmony_ci  hb_auto_trace_t<HB_DEBUG_SUBSET, bool> trace \
435cb93a386Sopenharmony_ci  (&c->debug_depth, c->get_name (), this, HB_FUNC, \
436cb93a386Sopenharmony_ci   " ")
437cb93a386Sopenharmony_ci#else
438cb93a386Sopenharmony_ci#define TRACE_SUBSET(this) hb_no_trace_t<bool> trace
439cb93a386Sopenharmony_ci#endif
440cb93a386Sopenharmony_ci
441cb93a386Sopenharmony_ci#ifndef HB_DEBUG_SUBSET_REPACK
442cb93a386Sopenharmony_ci#define HB_DEBUG_SUBSET_REPACK (HB_DEBUG+0)
443cb93a386Sopenharmony_ci#endif
444cb93a386Sopenharmony_ci
445cb93a386Sopenharmony_ci#ifndef HB_DEBUG_DISPATCH
446cb93a386Sopenharmony_ci#define HB_DEBUG_DISPATCH ( \
447cb93a386Sopenharmony_ci	HB_DEBUG_APPLY + \
448cb93a386Sopenharmony_ci	HB_DEBUG_SANITIZE + \
449cb93a386Sopenharmony_ci	HB_DEBUG_SERIALIZE + \
450cb93a386Sopenharmony_ci	HB_DEBUG_SUBSET + \
451cb93a386Sopenharmony_ci	0)
452cb93a386Sopenharmony_ci#endif
453cb93a386Sopenharmony_ci#if HB_DEBUG_DISPATCH
454cb93a386Sopenharmony_ci#define TRACE_DISPATCH(this, format) \
455cb93a386Sopenharmony_ci	hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
456cb93a386Sopenharmony_ci	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
457cb93a386Sopenharmony_ci	 "format %d", (int) format)
458cb93a386Sopenharmony_ci#else
459cb93a386Sopenharmony_ci#define TRACE_DISPATCH(this, format) hb_no_trace_t<typename context_t::return_t> trace
460cb93a386Sopenharmony_ci#endif
461cb93a386Sopenharmony_ci
462cb93a386Sopenharmony_ci
463cb93a386Sopenharmony_ci#endif /* HB_DEBUG_HH */
464