Bug Summary

File:jdk/src/java.desktop/share/native/libharfbuzz/hb-algs.hh
Warning:line 924, column 30
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name hb-ot-font.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -D LIBC=gnu -D _GNU_SOURCE -D _REENTRANT -D _LARGEFILE64_SOURCE -D LINUX -D DEBUG -D _LITTLE_ENDIAN -D ARCH="amd64" -D amd64 -D _LP64=1 -D GETPAGESIZE -D HAVE_MPROTECT -D HAVE_PTHREAD -D HAVE_SYSCONF -D HAVE_SYS_MMAN_H -D HAVE_UNISTD_H -D HB_NO_PRAGMA_GCC_DIAGNOSTIC -D HAVE_INTEL_ATOMIC_PRIMITIVES -I /usr/include/freetype2 -D LE_STANDALONE -D HEADLESS -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/libfontmanager -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libfontmanager -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/headers/java.desktop -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/common/awt -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/common/font -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/font -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/libawt/java2d -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt/java2d -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt/java2d/pipe -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt/java2d/loops -D _FORTIFY_SOURCE=2 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-unused -Wno-type-limits -Wno-missing-field-initializers -Wno-strict-aliasing -Wno-reorder -Wno-delete-non-virtual-dtor -Wno-strict-overflow -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-unused-result -Wno-extra -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c++ /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc

/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc

1/*
2 * Copyright © 2011,2014 Google, Inc.
3 *
4 * This is part of HarfBuzz, a text shaping library.
5 *
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
11 *
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 * DAMAGE.
17 *
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 *
24 * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
25 */
26
27#include "hb.hh"
28
29#ifndef HB_NO_OT_FONT
30
31#include "hb-ot.h"
32
33#include "hb-font.hh"
34#include "hb-machinery.hh"
35#include "hb-ot-face.hh"
36
37#include "hb-ot-cmap-table.hh"
38#include "hb-ot-glyf-table.hh"
39#include "hb-ot-cff1-table.hh"
40#include "hb-ot-cff2-table.hh"
41#include "hb-ot-hmtx-table.hh"
42#include "hb-ot-os2-table.hh"
43#include "hb-ot-post-table.hh"
44#include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
45#include "hb-ot-vorg-table.hh"
46#include "hb-ot-color-cbdt-table.hh"
47#include "hb-ot-color-sbix-table.hh"
48
49
50/**
51 * SECTION:hb-ot-font
52 * @title: hb-ot-font
53 * @short_description: OpenType font implementation
54 * @include: hb-ot.h
55 *
56 * Functions for using OpenType fonts with hb_shape(). Note that fonts returned
57 * by hb_font_create() default to using these functions, so most clients would
58 * never need to call these functions directly.
59 **/
60
61
62static hb_bool_t
63hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED__attribute__((unused)),
64 void *font_data,
65 hb_codepoint_t unicode,
66 hb_codepoint_t *glyph,
67 void *user_data HB_UNUSED__attribute__((unused)))
68{
69 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
70 return ot_face->cmap->get_nominal_glyph (unicode, glyph);
71}
72
73static unsigned int
74hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED__attribute__((unused)),
75 void *font_data,
76 unsigned int count,
77 const hb_codepoint_t *first_unicode,
78 unsigned int unicode_stride,
79 hb_codepoint_t *first_glyph,
80 unsigned int glyph_stride,
81 void *user_data HB_UNUSED__attribute__((unused)))
82{
83 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
84 return ot_face->cmap->get_nominal_glyphs (count,
85 first_unicode, unicode_stride,
86 first_glyph, glyph_stride);
87}
88
89static hb_bool_t
90hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED__attribute__((unused)),
91 void *font_data,
92 hb_codepoint_t unicode,
93 hb_codepoint_t variation_selector,
94 hb_codepoint_t *glyph,
95 void *user_data HB_UNUSED__attribute__((unused)))
96{
97 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
98 return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph);
99}
100
101static void
102hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
103 unsigned count,
104 const hb_codepoint_t *first_glyph,
105 unsigned glyph_stride,
106 hb_position_t *first_advance,
107 unsigned advance_stride,
108 void *user_data HB_UNUSED__attribute__((unused)))
109{
110 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
111 const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
112
113 for (unsigned int i = 0; i < count; i++)
114 {
115 *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font));
116 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
117 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
118 }
119}
120
121static void
122hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
123 unsigned count,
124 const hb_codepoint_t *first_glyph,
125 unsigned glyph_stride,
126 hb_position_t *first_advance,
127 unsigned advance_stride,
128 void *user_data HB_UNUSED__attribute__((unused)))
129{
130 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
131 const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
132
133 for (unsigned int i = 0; i < count; i++)
134 {
135 *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
136 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
137 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
138 }
139}
140
141static hb_bool_t
142hb_ot_get_glyph_v_origin (hb_font_t *font,
143 void *font_data,
144 hb_codepoint_t glyph,
145 hb_position_t *x,
146 hb_position_t *y,
147 void *user_data HB_UNUSED__attribute__((unused)))
148{
149 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
150
151 *x = font->get_glyph_h_advance (glyph) / 2;
152
153#ifndef HB_NO_OT_FONT_CFF
154 const OT::VORG &VORG = *ot_face->VORG;
155 if (VORG.has_data ())
156 {
157 *y = font->em_scale_y (VORG.get_y_origin (glyph));
158 return true;
159 }
160#endif
161
162 hb_glyph_extents_t extents = {0};
163 if (ot_face->glyf->get_extents (font, glyph, &extents))
164 {
165 const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
166 hb_position_t tsb = vmtx.get_side_bearing (font, glyph);
167 *y = extents.y_bearing + font->em_scale_y (tsb);
168 return true;
169 }
170
171 hb_font_extents_t font_extents;
172 font->get_h_extents_with_fallback (&font_extents);
173 *y = font_extents.ascender;
174
175 return true;
176}
177
178static hb_bool_t
179hb_ot_get_glyph_extents (hb_font_t *font,
180 void *font_data,
181 hb_codepoint_t glyph,
182 hb_glyph_extents_t *extents,
183 void *user_data HB_UNUSED__attribute__((unused)))
184{
185 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
186
187#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
188 if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
189#endif
190 if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
191#ifndef HB_NO_OT_FONT_CFF
192 if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
193 if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
194#endif
195#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
196 if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
197#endif
198
199 // TODO Hook up side-bearings variations.
200 return false;
201}
202
203#ifndef HB_NO_OT_FONT_GLYPH_NAMES
204static hb_bool_t
205hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED__attribute__((unused)),
206 void *font_data,
207 hb_codepoint_t glyph,
208 char *name, unsigned int size,
209 void *user_data HB_UNUSED__attribute__((unused)))
210{
211 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
212 if (ot_face->post->get_glyph_name (glyph, name, size)) return true;
213#ifndef HB_NO_OT_FONT_CFF
214 if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true;
215#endif
216 return false;
217}
218static hb_bool_t
219hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED__attribute__((unused)),
220 void *font_data,
221 const char *name, int len,
222 hb_codepoint_t *glyph,
223 void *user_data HB_UNUSED__attribute__((unused)))
224{
225 const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
226 if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true;
1
Calling 'accelerator_t::get_glyph_from_name'
227#ifndef HB_NO_OT_FONT_CFF
228 if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true;
229#endif
230 return false;
231}
232#endif
233
234static hb_bool_t
235hb_ot_get_font_h_extents (hb_font_t *font,
236 void *font_data HB_UNUSED__attribute__((unused)),
237 hb_font_extents_t *metrics,
238 void *user_data HB_UNUSED__attribute__((unused)))
239{
240 return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
241 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
242 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
243}
244
245static hb_bool_t
246hb_ot_get_font_v_extents (hb_font_t *font,
247 void *font_data HB_UNUSED__attribute__((unused)),
248 hb_font_extents_t *metrics,
249 void *user_data HB_UNUSED__attribute__((unused)))
250{
251 return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_ASCENDER, &metrics->ascender) &&
252 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_DESCENDER, &metrics->descender) &&
253 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap);
254}
255
256#if HB_USE_ATEXIT0
257static void free_static_ot_funcs ();
258#endif
259
260static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
261{
262 static hb_font_funcs_t *create ()
263 {
264 hb_font_funcs_t *funcs = hb_font_funcs_create ();
265
266 hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
267 hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
268 hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
269 hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
270 hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
271 hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
272 hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
273 //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
274 hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
275 hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
276 //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
277#ifndef HB_NO_OT_FONT_GLYPH_NAMES
278 hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
279 hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr);
280#endif
281
282 hb_font_funcs_make_immutable (funcs);
283
284#if HB_USE_ATEXIT0
285 atexit (free_static_ot_funcs);
286#endif
287
288 return funcs;
289 }
290} static_ot_funcs;
291
292#if HB_USE_ATEXIT0
293static
294void free_static_ot_funcs ()
295{
296 static_ot_funcs.free_instance ();
297}
298#endif
299
300static hb_font_funcs_t *
301_hb_ot_get_font_funcs ()
302{
303 return static_ot_funcs.get_unconst ();
304}
305
306
307/**
308 * hb_ot_font_set_funcs:
309 * @font: #hb_font_t to work upon
310 *
311 * Sets the font functions to use when working with @font.
312 *
313 * Since: 0.9.28
314 **/
315void
316hb_ot_font_set_funcs (hb_font_t *font)
317{
318 hb_font_set_funcs (font,
319 _hb_ot_get_font_funcs (),
320 &font->face->table,
321 nullptr);
322}
323
324#ifndef HB_NO_VAR
325int
326_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
327{
328 return font->face->table.glyf->get_side_bearing_var (font, glyph, is_vertical);
329}
330
331unsigned
332_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
333{
334 return font->face->table.glyf->get_advance_var (font, glyph, is_vertical);
335}
336#endif
337
338
339#endif

/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh

1/*
2 * Copyright © 2016 Google, Inc.
3 *
4 * This is part of HarfBuzz, a text shaping library.
5 *
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
11 *
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 * DAMAGE.
17 *
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 *
24 * Google Author(s): Behdad Esfahbod
25 */
26
27#ifndef HB_OT_POST_TABLE_HH
28#define HB_OT_POST_TABLE_HH
29
30#include "hb-open-type.hh"
31
32#define HB_STRING_ARRAY_NAME format1_names
33#define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh"
34#include "hb-string-array.hh"
35#undef HB_STRING_ARRAY_LIST
36#undef HB_STRING_ARRAY_NAME
37
38/*
39 * post -- PostScript
40 * https://docs.microsoft.com/en-us/typography/opentype/spec/post
41 */
42#define HB_OT_TAG_post((hb_tag_t)((((uint32_t)('p')&0xFF)<<24)|(((uint32_t
)('o')&0xFF)<<16)|(((uint32_t)('s')&0xFF)<<
8)|((uint32_t)('t')&0xFF)))
HB_TAG('p','o','s','t')((hb_tag_t)((((uint32_t)('p')&0xFF)<<24)|(((uint32_t
)('o')&0xFF)<<16)|(((uint32_t)('s')&0xFF)<<
8)|((uint32_t)('t')&0xFF)))
43
44
45namespace OT {
46
47
48struct postV2Tail
49{
50 friend struct post;
51
52 bool sanitize (hb_sanitize_context_t *c) const
53 {
54 TRACE_SANITIZE (this)hb_no_trace_t<bool> trace;
55 return_trace (glyphNameIndex.sanitize (c))return trace.ret (glyphNameIndex.sanitize (c), __PRETTY_FUNCTION__
, 55)
;
56 }
57
58 protected:
59 ArrayOf<HBUINT16> glyphNameIndex; /* This is not an offset, but is the
60 * ordinal number of the glyph in 'post'
61 * string tables. */
62/*UnsizedArrayOf<HBUINT8>
63 namesX;*/ /* Glyph names with length bytes [variable]
64 * (a Pascal string). */
65
66 public:
67 DEFINE_SIZE_ARRAY (2, glyphNameIndex)void _compiles_assertion_on_line_67 () const { (void) (glyphNameIndex
)[0].static_size; } void _instance_assertion_on_line_67 () const
{ static_assert ((sizeof (*this) == (2) + (1 +0) * sizeof ((
glyphNameIndex)[0])), ""); } static constexpr unsigned null_size
= (2); static constexpr unsigned min_size = (2)
;
68};
69
70struct post
71{
72 static constexpr hb_tag_t tableTag = HB_OT_TAG_post((hb_tag_t)((((uint32_t)('p')&0xFF)<<24)|(((uint32_t
)('o')&0xFF)<<16)|(((uint32_t)('s')&0xFF)<<
8)|((uint32_t)('t')&0xFF)))
;
73
74 void serialize (hb_serialize_context_t *c) const
75 {
76 post *post_prime = c->allocate_min<post> ();
77 if (unlikely (!post_prime)(__builtin_expect (!!(!post_prime), 0))) return;
78
79 memcpy (post_prime, this, post::min_size);
80 post_prime->version.major = 3; // Version 3 does not have any glyph names.
81 }
82
83 bool subset (hb_subset_context_t *c) const
84 {
85 TRACE_SUBSET (this)hb_no_trace_t<bool> trace;
86 post *post_prime = c->serializer->start_embed<post> ();
87 if (unlikely (!post_prime)(__builtin_expect (!!(!post_prime), 0))) return_trace (false)return trace.ret (false, __PRETTY_FUNCTION__, 87);
88
89 serialize (c->serializer);
90
91 return_trace (true)return trace.ret (true, __PRETTY_FUNCTION__, 91);
92 }
93
94 struct accelerator_t
95 {
96 void init (hb_face_t *face)
97 {
98 index_to_offset.init ();
99
100 table = hb_sanitize_context_t ().reference_table<post> (face);
101 unsigned int table_length = table.get_length ();
102
103 version = table->version.to_int ();
104 if (version != 0x00020000) return;
105
106 const postV2Tail &v2 = table->v2X;
107
108 glyphNameIndex = &v2.glyphNameIndex;
109 pool = &StructAfter<uint8_t> (v2.glyphNameIndex);
110
111 const uint8_t *end = (const uint8_t *) (const void *) table + table_length;
112 for (const uint8_t *data = pool;
113 index_to_offset.length < 65535 && data < end && data + *data < end;
114 data += 1 + *data)
115 index_to_offset.push (data - pool);
116 }
117 void fini ()
118 {
119 index_to_offset.fini ();
120 free (gids_sorted_by_name.get ());
121 table.destroy ();
122 }
123
124 bool get_glyph_name (hb_codepoint_t glyph,
125 char *buf, unsigned int buf_len) const
126 {
127 hb_bytes_t s = find_glyph_name (glyph);
128 if (!s.length) return false;
129 if (!buf_len) return true;
130 unsigned int len = hb_min (buf_len - 1, s.length);
131 strncpy (buf, s.arrayZ, len);
132 buf[len] = '\0';
133 return true;
134 }
135
136 bool get_glyph_from_name (const char *name, int len,
137 hb_codepoint_t *glyph) const
138 {
139 unsigned int count = get_glyph_count ();
140 if (unlikely (!count)(__builtin_expect (!!(!count), 0))) return false;
2
Assuming 'count' is not equal to 0
3
Taking false branch
141
142 if (len < 0) len = strlen (name);
4
Assuming 'len' is < 0
5
Taking true branch
143
144 if (unlikely (!len)(__builtin_expect (!!(!len), 0))) return false;
6
Assuming 'len' is not equal to 0
7
Taking false branch
145
146 retry:
147 uint16_t *gids = gids_sorted_by_name.get ();
148
149 if (unlikely (!gids)(__builtin_expect (!!(!gids), 0)))
8
Assuming 'gids' is null
9
Taking true branch
150 {
151 gids = (uint16_t *) malloc (count * sizeof (gids[0]));
10
Storing uninitialized value
152 if (unlikely (!gids)(__builtin_expect (!!(!gids), 0)))
11
Assuming 'gids' is non-null
12
Taking false branch
153 return false; /* Anything better?! */
154
155 for (unsigned int i = 0; i
12.1
'i' is < 'count'
12.1
'i' is < 'count'
12.1
'i' is < 'count'
< count
; i++)
13
Loop condition is true. Entering loop body
14
Assuming 'i' is < 'count'
15
Loop condition is true. Entering loop body
16
Assuming 'i' is >= 'count'
17
Loop condition is false. Execution continues on line 157
156 gids[i] = i;
157 hb_qsort (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
18
Calling 'hb_qsort'
158
159 if (unlikely (!gids_sorted_by_name.cmpexch (nullptr, gids))(__builtin_expect (!!(!gids_sorted_by_name.cmpexch (nullptr, gids
)), 0))
)
160 {
161 free (gids);
162 goto retry;
163 }
164 }
165
166 hb_bytes_t st (name, len);
167 auto* gid = hb_bsearch (st, gids, count, sizeof (gids[0]), cmp_key, (void *) this);
168 if (gid)
169 {
170 *glyph = *gid;
171 return true;
172 }
173
174 return false;
175 }
176
177 hb_blob_ptr_t<post> table;
178
179 protected:
180
181 unsigned int get_glyph_count () const
182 {
183 if (version == 0x00010000)
184 return format1_names_length;
185
186 if (version == 0x00020000)
187 return glyphNameIndex->len;
188
189 return 0;
190 }
191
192 static int cmp_gids (const void *pa, const void *pb, void *arg)
193 {
194 const accelerator_t *thiz = (const accelerator_t *) arg;
195 uint16_t a = * (const uint16_t *) pa;
196 uint16_t b = * (const uint16_t *) pb;
197 return thiz->find_glyph_name (b).cmp (thiz->find_glyph_name (a));
198 }
199
200 static int cmp_key (const void *pk, const void *po, void *arg)
201 {
202 const accelerator_t *thiz = (const accelerator_t *) arg;
203 const hb_bytes_t *key = (const hb_bytes_t *) pk;
204 uint16_t o = * (const uint16_t *) po;
205 return thiz->find_glyph_name (o).cmp (*key);
206 }
207
208 hb_bytes_t find_glyph_name (hb_codepoint_t glyph) const
209 {
210 if (version == 0x00010000)
211 {
212 if (glyph >= format1_names_length)
213 return hb_bytes_t ();
214
215 return format1_names (glyph);
216 }
217
218 if (version != 0x00020000 || glyph >= glyphNameIndex->len)
219 return hb_bytes_t ();
220
221 unsigned int index = glyphNameIndex->arrayZ[glyph];
222 if (index < format1_names_length)
223 return format1_names (index);
224 index -= format1_names_length;
225
226 if (index >= index_to_offset.length)
227 return hb_bytes_t ();
228 unsigned int offset = index_to_offset[index];
229
230 const uint8_t *data = pool + offset;
231 unsigned int name_length = *data;
232 data++;
233
234 return hb_bytes_t ((const char *) data, name_length);
235 }
236
237 private:
238 uint32_t version;
239 const ArrayOf<HBUINT16> *glyphNameIndex;
240 hb_vector_t<uint32_t> index_to_offset;
241 const uint8_t *pool;
242 hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
243 };
244
245 bool has_data () const { return version.to_int (); }
246
247 bool sanitize (hb_sanitize_context_t *c) const
248 {
249 TRACE_SANITIZE (this)hb_no_trace_t<bool> trace;
250 return_trace (likely (c->check_struct (this) &&return trace.ret ((__builtin_expect (!!(c->check_struct (this
) && (version.to_int () == 0x00010000 || (version.to_int
() == 0x00020000 && v2X.sanitize (c)) || version.to_int
() == 0x00030000)), 1)), __PRETTY_FUNCTION__, 253)
251 (version.to_int () == 0x00010000 ||return trace.ret ((__builtin_expect (!!(c->check_struct (this
) && (version.to_int () == 0x00010000 || (version.to_int
() == 0x00020000 && v2X.sanitize (c)) || version.to_int
() == 0x00030000)), 1)), __PRETTY_FUNCTION__, 253)
252 (version.to_int () == 0x00020000 && v2X.sanitize (c)) ||return trace.ret ((__builtin_expect (!!(c->check_struct (this
) && (version.to_int () == 0x00010000 || (version.to_int
() == 0x00020000 && v2X.sanitize (c)) || version.to_int
() == 0x00030000)), 1)), __PRETTY_FUNCTION__, 253)
253 version.to_int () == 0x00030000)))return trace.ret ((__builtin_expect (!!(c->check_struct (this
) && (version.to_int () == 0x00010000 || (version.to_int
() == 0x00020000 && v2X.sanitize (c)) || version.to_int
() == 0x00030000)), 1)), __PRETTY_FUNCTION__, 253)
;
254 }
255
256 public:
257 FixedVersion<>version; /* 0x00010000 for version 1.0
258 * 0x00020000 for version 2.0
259 * 0x00025000 for version 2.5 (deprecated)
260 * 0x00030000 for version 3.0 */
261 HBFixed italicAngle; /* Italic angle in counter-clockwise degrees
262 * from the vertical. Zero for upright text,
263 * negative for text that leans to the right
264 * (forward). */
265 FWORD underlinePosition; /* This is the suggested distance of the top
266 * of the underline from the baseline
267 * (negative values indicate below baseline).
268 * The PostScript definition of this FontInfo
269 * dictionary key (the y coordinate of the
270 * center of the stroke) is not used for
271 * historical reasons. The value of the
272 * PostScript key may be calculated by
273 * subtracting half the underlineThickness
274 * from the value of this field. */
275 FWORD underlineThickness; /* Suggested values for the underline
276 thickness. */
277 HBUINT32 isFixedPitch; /* Set to 0 if the font is proportionally
278 * spaced, non-zero if the font is not
279 * proportionally spaced (i.e. monospaced). */
280 HBUINT32 minMemType42; /* Minimum memory usage when an OpenType font
281 * is downloaded. */
282 HBUINT32 maxMemType42; /* Maximum memory usage when an OpenType font
283 * is downloaded. */
284 HBUINT32 minMemType1; /* Minimum memory usage when an OpenType font
285 * is downloaded as a Type 1 font. */
286 HBUINT32 maxMemType1; /* Maximum memory usage when an OpenType font
287 * is downloaded as a Type 1 font. */
288 postV2Tail v2X;
289 DEFINE_SIZE_MIN (32)void _instance_assertion_on_line_289 () const { static_assert
((sizeof (*this) >= (32)), ""); } static constexpr unsigned
null_size = (32); static constexpr unsigned min_size = (32)
;
290};
291
292struct post_accelerator_t : post::accelerator_t {};
293
294} /* namespace OT */
295
296
297#endif /* HB_OT_POST_TABLE_HH */

/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-algs.hh

1/*
2 * Copyright © 2017 Google, Inc.
3 * Copyright © 2019 Facebook, Inc.
4 *
5 * This is part of HarfBuzz, a text shaping library.
6 *
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
12 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE.
18 *
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 *
25 * Google Author(s): Behdad Esfahbod
26 * Facebook Author(s): Behdad Esfahbod
27 */
28
29#ifndef HB_ALGS_HH
30#define HB_ALGS_HH
31
32#include "hb.hh"
33#include "hb-meta.hh"
34#include "hb-null.hh"
35#include "hb-number.hh"
36
37
38/*
39 * Flags
40 */
41
42/* Enable bitwise ops on enums marked as flags_t */
43/* To my surprise, looks like the function resolver is happy to silently cast
44 * one enum to another... So this doesn't provide the type-checking that I
45 * originally had in mind... :(.
46 *
47 * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
48 */
49#ifdef _MSC_VER
50# pragma warning(disable:4200)
51# pragma warning(disable:4800)
52#endif
53#define HB_MARK_AS_FLAG_T(T)extern "C++" { static inline constexpr T operator | (T l, T r
) { return T ((unsigned) l | (unsigned) r); } static inline constexpr
T operator & (T l, T r) { return T ((unsigned) l & (
unsigned) r); } static inline constexpr T operator ^ (T l, T r
) { return T ((unsigned) l ^ (unsigned) r); } static inline constexpr
T operator ~ (T r) { return T (~(unsigned int) r); } static inline
T& operator |= (T &l, T r) { l = l | r; return l; } static
inline T& operator &= (T& l, T r) { l = l & r
; return l; } static inline T& operator ^= (T& l, T r
) { l = l ^ r; return l; } } static_assert (true, "")
\
54 extern "C++" { \
55 static inline constexpr T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
56 static inline constexpr T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
57 static inline constexpr T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
58 static inline constexpr T operator ~ (T r) { return T (~(unsigned int) r); } \
59 static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
60 static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
61 static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
62 } \
63 static_assert (true, "")
64
65/* Useful for set-operations on small enums.
66 * For example, for testing "x ∈ {x1, x2, x3}" use:
67 * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
68 */
69#define FLAG(x)(static_assert_expr<(unsigned)(x) < 32>::value + (((
uint32_t) 1U) << (unsigned)(x)))
(static_assert_expr ((unsigned)(x) < 32)static_assert_expr<(unsigned)(x) < 32>::value + (((uint32_t) 1U) << (unsigned)(x)))
70#define FLAG_UNSAFE(x)((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)
(x)) : 0)
((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0)
71#define FLAG_RANGE(x,y)(static_assert_expr<(x) < (y)>::value + (static_assert_expr
<(unsigned)(y+1) < 32>::value + (((uint32_t) 1U) <<
(unsigned)(y+1))) - (static_assert_expr<(unsigned)(x) <
32>::value + (((uint32_t) 1U) << (unsigned)(x))))
(static_assert_expr ((x) < (y))static_assert_expr<(x) < (y)>::value + FLAG(y+1)(static_assert_expr<(unsigned)(y+1) < 32>::value + (
((uint32_t) 1U) << (unsigned)(y+1)))
- FLAG(x)(static_assert_expr<(unsigned)(x) < 32>::value + (((
uint32_t) 1U) << (unsigned)(x)))
)
72#define FLAG64(x)(static_assert_expr<(unsigned)(x) < 64>::value + (((
uint64_t) 1ULL) << (unsigned)(x)))
(static_assert_expr ((unsigned)(x) < 64)static_assert_expr<(unsigned)(x) < 64>::value + (((uint64_t) 1ULL) << (unsigned)(x)))
73#define FLAG64_UNSAFE(x)((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned
)(x)) : 0)
((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
74
75
76/*
77 * Big-endian integers.
78 */
79
80/* Endian swap, used in Windows related backends */
81static inline constexpr uint16_t hb_uint16_swap (uint16_t v)
82{ return (v >> 8) | (v << 8); }
83static inline constexpr uint32_t hb_uint32_swap (uint32_t v)
84{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
85
86template <typename Type, int Bytes = sizeof (Type)>
87struct BEInt;
88template <typename Type>
89struct BEInt<Type, 1>
90{
91 public:
92 BEInt () = default;
93 constexpr BEInt (Type V) : v {uint8_t (V)} {}
94 constexpr operator Type () const { return v; }
95 private: uint8_t v;
96};
97template <typename Type>
98struct BEInt<Type, 2>
99{
100 public:
101 BEInt () = default;
102 constexpr BEInt (Type V) : v {uint8_t ((V >> 8) & 0xFF),
103 uint8_t ((V ) & 0xFF)} {}
104
105 struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
106 constexpr operator Type () const
107 {
108#if ((defined(__GNUC__4) && __GNUC__4 >= 5) || defined(__clang__1)) && \
109 defined(__BYTE_ORDER1234) && \
110 (__BYTE_ORDER1234 == __LITTLE_ENDIAN1234 || __BYTE_ORDER1234 == __BIG_ENDIAN4321)
111 /* Spoon-feed the compiler a big-endian integer with alignment 1.
112 * https://github.com/harfbuzz/harfbuzz/pull/1398 */
113#if __BYTE_ORDER1234 == __LITTLE_ENDIAN1234
114 return __builtin_bswap16 (((packed_uint16_t *) this)->v);
115#else /* __BYTE_ORDER == __BIG_ENDIAN */
116 return ((packed_uint16_t *) this)->v;
117#endif
118#else
119 return (v[0] << 8)
120 + (v[1] );
121#endif
122 }
123 private: uint8_t v[2];
124};
125template <typename Type>
126struct BEInt<Type, 3>
127{
128 static_assert (!hb_is_signed (Type)hb_is_signed<Type>::value, "");
129 public:
130 BEInt () = default;
131 constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF),
132 uint8_t ((V >> 8) & 0xFF),
133 uint8_t ((V ) & 0xFF)} {}
134
135 constexpr operator Type () const { return (v[0] << 16)
136 + (v[1] << 8)
137 + (v[2] ); }
138 private: uint8_t v[3];
139};
140template <typename Type>
141struct BEInt<Type, 4>
142{
143 public:
144 BEInt () = default;
145 constexpr BEInt (Type V) : v {uint8_t ((V >> 24) & 0xFF),
146 uint8_t ((V >> 16) & 0xFF),
147 uint8_t ((V >> 8) & 0xFF),
148 uint8_t ((V ) & 0xFF)} {}
149 constexpr operator Type () const { return (v[0] << 24)
150 + (v[1] << 16)
151 + (v[2] << 8)
152 + (v[3] ); }
153 private: uint8_t v[4];
154};
155
156/* Floats. */
157
158/* We want our rounding towards +infinity. */
159static inline float
160_hb_roundf (float x) { return floorf (x + .5f); }
161#define roundf(x)_hb_roundf(x) _hb_roundf(x)
162
163
164/* Encodes three unsigned integers in one 64-bit number. If the inputs have more than 21 bits,
165 * values will be truncated / overlap, and might not decode exactly. */
166#define HB_CODEPOINT_ENCODE3(x,y,z)(((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) |
(uint64_t) (z))
(((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z))
167#define HB_CODEPOINT_DECODE3_1(v)((hb_codepoint_t) ((v) >> 42)) ((hb_codepoint_t) ((v) >> 42))
168#define HB_CODEPOINT_DECODE3_2(v)((hb_codepoint_t) ((v) >> 21) & 0x1FFFFFu) ((hb_codepoint_t) ((v) >> 21) & 0x1FFFFFu)
169#define HB_CODEPOINT_DECODE3_3(v)((hb_codepoint_t) (v) & 0x1FFFFFu) ((hb_codepoint_t) (v) & 0x1FFFFFu)
170
171/* Custom encoding used by hb-ucd. */
172#define HB_CODEPOINT_ENCODE3_11_7_14(x,y,z)(((uint32_t) ((x) & 0x07FFu) << 21) | (((uint32_t) (
y) & 0x007Fu) << 14) | (uint32_t) ((z) & 0x3FFFu
))
(((uint32_t) ((x) & 0x07FFu) << 21) | (((uint32_t) (y) & 0x007Fu) << 14) | (uint32_t) ((z) & 0x3FFFu))
173#define HB_CODEPOINT_DECODE3_11_7_14_1(v)((hb_codepoint_t) ((v) >> 21)) ((hb_codepoint_t) ((v) >> 21))
174#define HB_CODEPOINT_DECODE3_11_7_14_2(v)((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300)
175#define HB_CODEPOINT_DECODE3_11_7_14_3(v)((hb_codepoint_t) (v) & 0x3FFFu) ((hb_codepoint_t) (v) & 0x3FFFu)
176
177
178struct
179{
180 /* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
181 template <typename T> constexpr auto
182 operator () (T&& v) const HB_AUTO_RETURN ( hb_forward<T> (v) )-> decltype ((hb_forward<T> (v))) { return (hb_forward
<T> (v)); }
183}
184HB_FUNCOBJ (hb_identity)static const hb_identity __attribute__((unused));
185struct
186{
187 /* Like identity(), but only retains lvalue-references. Rvalues are returned as rvalues. */
188 template <typename T> constexpr T&
189 operator () (T& v) const { return v; }
190
191 template <typename T> constexpr hb_remove_reference<T>
192 operator () (T&& v) const { return v; }
193}
194HB_FUNCOBJ (hb_lidentity)static const hb_lidentity __attribute__((unused));
195struct
196{
197 /* Like identity(), but always returns rvalue. */
198 template <typename T> constexpr hb_remove_reference<T>
199 operator () (T&& v) const { return v; }
200}
201HB_FUNCOBJ (hb_ridentity)static const hb_ridentity __attribute__((unused));
202
203struct
204{
205 template <typename T> constexpr bool
206 operator () (T&& v) const { return bool (hb_forward<T> (v)); }
207}
208HB_FUNCOBJ (hb_bool)static const hb_bool __attribute__((unused));
209
210struct
211{
212 private:
213
214 template <typename T> constexpr auto
215 impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())-> hb_head_t<uint32_t, decltype ((hb_deref (v).hash ())
)> { return (hb_deref (v).hash ()); }
216
217 template <typename T,
218 hb_enable_if (hb_is_integral (T))typename hb_enable_if<(hb_is_integral<T>::value)>
::type* = nullptr
> constexpr auto
219 impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN-> decltype (((uint32_t) v * 2654435761u)) { return ((uint32_t
) v * 2654435761u); }
220 (-> decltype (((uint32_t) v * 2654435761u)) { return ((uint32_t
) v * 2654435761u); }
221 /* Knuth's multiplicative method: */-> decltype (((uint32_t) v * 2654435761u)) { return ((uint32_t
) v * 2654435761u); }
222 (uint32_t) v * 2654435761u-> decltype (((uint32_t) v * 2654435761u)) { return ((uint32_t
) v * 2654435761u); }
223 )-> decltype (((uint32_t) v * 2654435761u)) { return ((uint32_t
) v * 2654435761u); }
224
225 public:
226
227 template <typename T> constexpr auto
228 operator () (const T& v) const HB_RETURN (uint32_t, impl (v, hb_prioritize))-> hb_head_t<uint32_t, decltype ((impl (v, hb_priority<
16> ())))> { return (impl (v, hb_priority<16> ())
); }
229}
230HB_FUNCOBJ (hb_hash)static const hb_hash __attribute__((unused));
231
232
233struct
234{
235 private:
236
237 /* Pointer-to-member-function. */
238 template <typename Appl, typename T, typename ...Ts> auto
239 impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN-> decltype (((hb_deref (hb_forward<T> (v)).*hb_forward
<Appl> (a)) (hb_forward<Ts> (ds)...))) { return (
(hb_deref (hb_forward<T> (v)).*hb_forward<Appl> (
a)) (hb_forward<Ts> (ds)...)); }
240 ((hb_deref (hb_forward<T> (v)).*hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...))-> decltype (((hb_deref (hb_forward<T> (v)).*hb_forward
<Appl> (a)) (hb_forward<Ts> (ds)...))) { return (
(hb_deref (hb_forward<T> (v)).*hb_forward<Appl> (
a)) (hb_forward<Ts> (ds)...)); }
241
242 /* Pointer-to-member. */
243 template <typename Appl, typename T> auto
244 impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN-> decltype (((hb_deref (hb_forward<T> (v))).*hb_forward
<Appl> (a))) { return ((hb_deref (hb_forward<T> (
v))).*hb_forward<Appl> (a)); }
245 ((hb_deref (hb_forward<T> (v))).*hb_forward<Appl> (a))-> decltype (((hb_deref (hb_forward<T> (v))).*hb_forward
<Appl> (a))) { return ((hb_deref (hb_forward<T> (
v))).*hb_forward<Appl> (a)); }
246
247 /* Operator(). */
248 template <typename Appl, typename ...Ts> auto
249 impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN-> decltype ((hb_deref (hb_forward<Appl> (a)) (hb_forward
<Ts> (ds)...))) { return (hb_deref (hb_forward<Appl>
(a)) (hb_forward<Ts> (ds)...)); }
250 (hb_deref (hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...))-> decltype ((hb_deref (hb_forward<Appl> (a)) (hb_forward
<Ts> (ds)...))) { return (hb_deref (hb_forward<Appl>
(a)) (hb_forward<Ts> (ds)...)); }
251
252 public:
253
254 template <typename Appl, typename ...Ts> auto
255 operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN-> decltype ((impl (hb_forward<Appl> (a), hb_priority
<16> (), hb_forward<Ts> (ds)...))) { return (impl
(hb_forward<Appl> (a), hb_priority<16> (), hb_forward
<Ts> (ds)...)); }
256 (-> decltype ((impl (hb_forward<Appl> (a), hb_priority
<16> (), hb_forward<Ts> (ds)...))) { return (impl
(hb_forward<Appl> (a), hb_priority<16> (), hb_forward
<Ts> (ds)...)); }
257 impl (hb_forward<Appl> (a),-> decltype ((impl (hb_forward<Appl> (a), hb_priority
<16> (), hb_forward<Ts> (ds)...))) { return (impl
(hb_forward<Appl> (a), hb_priority<16> (), hb_forward
<Ts> (ds)...)); }
258 hb_prioritize,-> decltype ((impl (hb_forward<Appl> (a), hb_priority
<16> (), hb_forward<Ts> (ds)...))) { return (impl
(hb_forward<Appl> (a), hb_priority<16> (), hb_forward
<Ts> (ds)...)); }
259 hb_forward<Ts> (ds)...)-> decltype ((impl (hb_forward<Appl> (a), hb_priority
<16> (), hb_forward<Ts> (ds)...))) { return (impl
(hb_forward<Appl> (a), hb_priority<16> (), hb_forward
<Ts> (ds)...)); }
260 )-> decltype ((impl (hb_forward<Appl> (a), hb_priority
<16> (), hb_forward<Ts> (ds)...))) { return (impl
(hb_forward<Appl> (a), hb_priority<16> (), hb_forward
<Ts> (ds)...)); }
261}
262HB_FUNCOBJ (hb_invoke)static const hb_invoke __attribute__((unused));
263
264template <unsigned Pos, typename Appl, typename V>
265struct hb_partial_t
266{
267 hb_partial_t (Appl a, V v) : a (a), v (v) {}
268
269 static_assert (Pos > 0, "");
270
271 template <typename ...Ts,
272 unsigned P = Pos,
273 hb_enable_if (P == 1)typename hb_enable_if<(P == 1)>::type* = nullptr> auto
274 operator () (Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl)(hb_declval<Appl> ()),
275 hb_declval (V)(hb_declval<V> ()),
276 hb_declval (Ts)(hb_declval<Ts> ())...))
277 {
278 return hb_invoke (hb_forward<Appl> (a),
279 hb_forward<V> (v),
280 hb_forward<Ts> (ds)...);
281 }
282 template <typename T0, typename ...Ts,
283 unsigned P = Pos,
284 hb_enable_if (P == 2)typename hb_enable_if<(P == 2)>::type* = nullptr> auto
285 operator () (T0&& d0, Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl)(hb_declval<Appl> ()),
286 hb_declval (T0)(hb_declval<T0> ()),
287 hb_declval (V)(hb_declval<V> ()),
288 hb_declval (Ts)(hb_declval<Ts> ())...))
289 {
290 return hb_invoke (hb_forward<Appl> (a),
291 hb_forward<T0> (d0),
292 hb_forward<V> (v),
293 hb_forward<Ts> (ds)...);
294 }
295
296 private:
297 hb_reference_wrapper<Appl> a;
298 V v;
299};
300template <unsigned Pos=1, typename Appl, typename V>
301auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN-> decltype ((( hb_partial_t<Pos, Appl, V> (a, v) ))
) { return (( hb_partial_t<Pos, Appl, V> (a, v) )); }
302(( hb_partial_t<Pos, Appl, V> (a, v) ))-> decltype ((( hb_partial_t<Pos, Appl, V> (a, v) ))
) { return (( hb_partial_t<Pos, Appl, V> (a, v) )); }
303
304/* The following, HB_PARTIALIZE, macro uses a particular corner-case
305 * of C++11 that is not particularly well-supported by all compilers.
306 * What's happening is that it's using "this" in a trailing return-type
307 * via decltype(). Broken compilers deduce the type of "this" pointer
308 * in that context differently from what it resolves to in the body
309 * of the function.
310 *
311 * One probable cause of this is that at the time of trailing return
312 * type declaration, "this" points to an incomplete type, whereas in
313 * the function body the type is complete. That doesn't justify the
314 * error in any way, but is probably what's happening.
315 *
316 * In the case of MSVC, we get around this by using C++14 "decltype(auto)"
317 * which deduces the type from the actual return statement. For gcc 4.8
318 * we use "+this" instead of "this" which produces an rvalue that seems
319 * to be deduced as the same type with this particular compiler, and seem
320 * to be fine as default code path as well.
321 */
322#ifdef _MSC_VER
323/* https://github.com/harfbuzz/harfbuzz/issues/1730 */ \
324#define HB_PARTIALIZE(Pos)template <typename _T> auto operator () (_T&& _v
) const -> decltype ((hb_partial<Pos> (+this, hb_forward
<_T> (_v)))) { return (hb_partial<Pos> (+this, hb_forward
<_T> (_v))); } static_assert (true, "")
\
325 template <typename _T> \
326 decltype(auto) operator () (_T&& _v) const \
327 { return hb_partial<Pos> (this, hb_forward<_T> (_v)); } \
328 static_assert (true, "")
329#else
330/* https://github.com/harfbuzz/harfbuzz/issues/1724 */
331#define HB_PARTIALIZE(Pos)template <typename _T> auto operator () (_T&& _v
) const -> decltype ((hb_partial<Pos> (+this, hb_forward
<_T> (_v)))) { return (hb_partial<Pos> (+this, hb_forward
<_T> (_v))); } static_assert (true, "")
\
332 template <typename _T> \
333 auto operator () (_T&& _v) const HB_AUTO_RETURN \-> decltype ((hb_partial<Pos> (+this, hb_forward<
_T> (_v)))) { return (hb_partial<Pos> (+this, hb_forward
<_T> (_v))); }
334 (hb_partial<Pos> (+this, hb_forward<_T> (_v)))-> decltype ((hb_partial<Pos> (+this, hb_forward<
_T> (_v)))) { return (hb_partial<Pos> (+this, hb_forward
<_T> (_v))); }
\
335 static_assert (true, "")
336#endif
337
338
339struct
340{
341 private:
342
343 template <typename Pred, typename Val> auto
344 impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN-> decltype ((hb_deref (hb_forward<Pred> (p)).has (hb_forward
<Val> (v)))) { return (hb_deref (hb_forward<Pred>
(p)).has (hb_forward<Val> (v))); }
345 (-> decltype ((hb_deref (hb_forward<Pred> (p)).has (hb_forward
<Val> (v)))) { return (hb_deref (hb_forward<Pred>
(p)).has (hb_forward<Val> (v))); }
346 hb_deref (hb_forward<Pred> (p)).has (hb_forward<Val> (v))-> decltype ((hb_deref (hb_forward<Pred> (p)).has (hb_forward
<Val> (v)))) { return (hb_deref (hb_forward<Pred>
(p)).has (hb_forward<Val> (v))); }
347 )-> decltype ((hb_deref (hb_forward<Pred> (p)).has (hb_forward
<Val> (v)))) { return (hb_deref (hb_forward<Pred>
(p)).has (hb_forward<Val> (v))); }
348
349 template <typename Pred, typename Val> auto
350 impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN-> decltype ((hb_invoke (hb_forward<Pred> (p), hb_forward
<Val> (v)))) { return (hb_invoke (hb_forward<Pred>
(p), hb_forward<Val> (v))); }
351 (-> decltype ((hb_invoke (hb_forward<Pred> (p), hb_forward
<Val> (v)))) { return (hb_invoke (hb_forward<Pred>
(p), hb_forward<Val> (v))); }
352 hb_invoke (hb_forward<Pred> (p),-> decltype ((hb_invoke (hb_forward<Pred> (p), hb_forward
<Val> (v)))) { return (hb_invoke (hb_forward<Pred>
(p), hb_forward<Val> (v))); }
353 hb_forward<Val> (v))-> decltype ((hb_invoke (hb_forward<Pred> (p), hb_forward
<Val> (v)))) { return (hb_invoke (hb_forward<Pred>
(p), hb_forward<Val> (v))); }
354 )-> decltype ((hb_invoke (hb_forward<Pred> (p), hb_forward
<Val> (v)))) { return (hb_invoke (hb_forward<Pred>
(p), hb_forward<Val> (v))); }
355
356 public:
357
358 template <typename Pred, typename Val> auto
359 operator () (Pred&& p, Val &&v) const HB_RETURN (bool,-> hb_head_t<bool, decltype ((impl (hb_forward<Pred>
(p), hb_forward<Val> (v), hb_priority<16> ())))>
{ return (impl (hb_forward<Pred> (p), hb_forward<Val
> (v), hb_priority<16> ())); }
360 impl (hb_forward<Pred> (p),-> hb_head_t<bool, decltype ((impl (hb_forward<Pred>
(p), hb_forward<Val> (v), hb_priority<16> ())))>
{ return (impl (hb_forward<Pred> (p), hb_forward<Val
> (v), hb_priority<16> ())); }
361 hb_forward<Val> (v),-> hb_head_t<bool, decltype ((impl (hb_forward<Pred>
(p), hb_forward<Val> (v), hb_priority<16> ())))>
{ return (impl (hb_forward<Pred> (p), hb_forward<Val
> (v), hb_priority<16> ())); }
362 hb_prioritize)-> hb_head_t<bool, decltype ((impl (hb_forward<Pred>
(p), hb_forward<Val> (v), hb_priority<16> ())))>
{ return (impl (hb_forward<Pred> (p), hb_forward<Val
> (v), hb_priority<16> ())); }
363 )-> hb_head_t<bool, decltype ((impl (hb_forward<Pred>
(p), hb_forward<Val> (v), hb_priority<16> ())))>
{ return (impl (hb_forward<Pred> (p), hb_forward<Val
> (v), hb_priority<16> ())); }
364}
365HB_FUNCOBJ (hb_has)static const hb_has __attribute__((unused));
366
367struct
368{
369 private:
370
371 template <typename Pred, typename Val> auto
372 impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN-> decltype ((hb_has (hb_forward<Pred> (p), hb_forward
<Val> (v)))) { return (hb_has (hb_forward<Pred> (
p), hb_forward<Val> (v))); }
373 (-> decltype ((hb_has (hb_forward<Pred> (p), hb_forward
<Val> (v)))) { return (hb_has (hb_forward<Pred> (
p), hb_forward<Val> (v))); }
374 hb_has (hb_forward<Pred> (p),-> decltype ((hb_has (hb_forward<Pred> (p), hb_forward
<Val> (v)))) { return (hb_has (hb_forward<Pred> (
p), hb_forward<Val> (v))); }
375 hb_forward<Val> (v))-> decltype ((hb_has (hb_forward<Pred> (p), hb_forward
<Val> (v)))) { return (hb_has (hb_forward<Pred> (
p), hb_forward<Val> (v))); }
376 )-> decltype ((hb_has (hb_forward<Pred> (p), hb_forward
<Val> (v)))) { return (hb_has (hb_forward<Pred> (
p), hb_forward<Val> (v))); }
377
378 template <typename Pred, typename Val> auto
379 impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN-> decltype ((hb_forward<Pred> (p) == hb_forward<
Val> (v))) { return (hb_forward<Pred> (p) == hb_forward
<Val> (v)); }
380 (-> decltype ((hb_forward<Pred> (p) == hb_forward<
Val> (v))) { return (hb_forward<Pred> (p) == hb_forward
<Val> (v)); }
381 hb_forward<Pred> (p) == hb_forward<Val> (v)-> decltype ((hb_forward<Pred> (p) == hb_forward<
Val> (v))) { return (hb_forward<Pred> (p) == hb_forward
<Val> (v)); }
382 )-> decltype ((hb_forward<Pred> (p) == hb_forward<
Val> (v))) { return (hb_forward<Pred> (p) == hb_forward
<Val> (v)); }
383
384 public:
385
386 template <typename Pred, typename Val> auto
387 operator () (Pred&& p, Val &&v) const HB_RETURN (bool,-> hb_head_t<bool, decltype ((impl (hb_forward<Pred>
(p), hb_forward<Val> (v), hb_priority<16> ())))>
{ return (impl (hb_forward<Pred> (p), hb_forward<Val
> (v), hb_priority<16> ())); }
388 impl (hb_forward<Pred> (p),-> hb_head_t<bool, decltype ((impl (hb_forward<Pred>
(p), hb_forward<Val> (v), hb_priority<16> ())))>
{ return (impl (hb_forward<Pred> (p), hb_forward<Val
> (v), hb_priority<16> ())); }
389 hb_forward<Val> (v),-> hb_head_t<bool, decltype ((impl (hb_forward<Pred>
(p), hb_forward<Val> (v), hb_priority<16> ())))>
{ return (impl (hb_forward<Pred> (p), hb_forward<Val
> (v), hb_priority<16> ())); }
390 hb_prioritize)-> hb_head_t<bool, decltype ((impl (hb_forward<Pred>
(p), hb_forward<Val> (v), hb_priority<16> ())))>
{ return (impl (hb_forward<Pred> (p), hb_forward<Val
> (v), hb_priority<16> ())); }
391 )-> hb_head_t<bool, decltype ((impl (hb_forward<Pred>
(p), hb_forward<Val> (v), hb_priority<16> ())))>
{ return (impl (hb_forward<Pred> (p), hb_forward<Val
> (v), hb_priority<16> ())); }
392}
393HB_FUNCOBJ (hb_match)static const hb_match __attribute__((unused));
394
395struct
396{
397 private:
398
399 template <typename Proj, typename Val> auto
400 impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN-> decltype ((hb_deref (hb_forward<Proj> (f)).get (hb_forward
<Val> (v)))) { return (hb_deref (hb_forward<Proj>
(f)).get (hb_forward<Val> (v))); }
401 (-> decltype ((hb_deref (hb_forward<Proj> (f)).get (hb_forward
<Val> (v)))) { return (hb_deref (hb_forward<Proj>
(f)).get (hb_forward<Val> (v))); }
402 hb_deref (hb_forward<Proj> (f)).get (hb_forward<Val> (v))-> decltype ((hb_deref (hb_forward<Proj> (f)).get (hb_forward
<Val> (v)))) { return (hb_deref (hb_forward<Proj>
(f)).get (hb_forward<Val> (v))); }
403 )-> decltype ((hb_deref (hb_forward<Proj> (f)).get (hb_forward
<Val> (v)))) { return (hb_deref (hb_forward<Proj>
(f)).get (hb_forward<Val> (v))); }
404
405 template <typename Proj, typename Val> auto
406 impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN-> decltype ((hb_invoke (hb_forward<Proj> (f), hb_forward
<Val> (v)))) { return (hb_invoke (hb_forward<Proj>
(f), hb_forward<Val> (v))); }
407 (-> decltype ((hb_invoke (hb_forward<Proj> (f), hb_forward
<Val> (v)))) { return (hb_invoke (hb_forward<Proj>
(f), hb_forward<Val> (v))); }
408 hb_invoke (hb_forward<Proj> (f),-> decltype ((hb_invoke (hb_forward<Proj> (f), hb_forward
<Val> (v)))) { return (hb_invoke (hb_forward<Proj>
(f), hb_forward<Val> (v))); }
409 hb_forward<Val> (v))-> decltype ((hb_invoke (hb_forward<Proj> (f), hb_forward
<Val> (v)))) { return (hb_invoke (hb_forward<Proj>
(f), hb_forward<Val> (v))); }
410 )-> decltype ((hb_invoke (hb_forward<Proj> (f), hb_forward
<Val> (v)))) { return (hb_invoke (hb_forward<Proj>
(f), hb_forward<Val> (v))); }
411
412 template <typename Proj, typename Val> auto
413 impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN-> decltype ((hb_forward<Proj> (f)[hb_forward<Val
> (v)])) { return (hb_forward<Proj> (f)[hb_forward<
Val> (v)]); }
414 (-> decltype ((hb_forward<Proj> (f)[hb_forward<Val
> (v)])) { return (hb_forward<Proj> (f)[hb_forward<
Val> (v)]); }
415 hb_forward<Proj> (f)[hb_forward<Val> (v)]-> decltype ((hb_forward<Proj> (f)[hb_forward<Val
> (v)])) { return (hb_forward<Proj> (f)[hb_forward<
Val> (v)]); }
416 )-> decltype ((hb_forward<Proj> (f)[hb_forward<Val
> (v)])) { return (hb_forward<Proj> (f)[hb_forward<
Val> (v)]); }
417
418 public:
419
420 template <typename Proj, typename Val> auto
421 operator () (Proj&& f, Val &&v) const HB_AUTO_RETURN-> decltype ((impl (hb_forward<Proj> (f), hb_forward
<Val> (v), hb_priority<16> ()))) { return (impl (
hb_forward<Proj> (f), hb_forward<Val> (v), hb_priority
<16> ())); }
422 (-> decltype ((impl (hb_forward<Proj> (f), hb_forward
<Val> (v), hb_priority<16> ()))) { return (impl (
hb_forward<Proj> (f), hb_forward<Val> (v), hb_priority
<16> ())); }
423 impl (hb_forward<Proj> (f),-> decltype ((impl (hb_forward<Proj> (f), hb_forward
<Val> (v), hb_priority<16> ()))) { return (impl (
hb_forward<Proj> (f), hb_forward<Val> (v), hb_priority
<16> ())); }
424 hb_forward<Val> (v),-> decltype ((impl (hb_forward<Proj> (f), hb_forward
<Val> (v), hb_priority<16> ()))) { return (impl (
hb_forward<Proj> (f), hb_forward<Val> (v), hb_priority
<16> ())); }
425 hb_prioritize)-> decltype ((impl (hb_forward<Proj> (f), hb_forward
<Val> (v), hb_priority<16> ()))) { return (impl (
hb_forward<Proj> (f), hb_forward<Val> (v), hb_priority
<16> ())); }
426 )-> decltype ((impl (hb_forward<Proj> (f), hb_forward
<Val> (v), hb_priority<16> ()))) { return (impl (
hb_forward<Proj> (f), hb_forward<Val> (v), hb_priority
<16> ())); }
427}
428HB_FUNCOBJ (hb_get)static const hb_get __attribute__((unused));
429
430struct
431{
432 private:
433
434 template <typename T1, typename T2> auto
435 impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN-> decltype ((hb_forward<T2> (v2).cmp (hb_forward<
T1> (v1)) == 0)) { return (hb_forward<T2> (v2).cmp (
hb_forward<T1> (v1)) == 0); }
436 (-> decltype ((hb_forward<T2> (v2).cmp (hb_forward<
T1> (v1)) == 0)) { return (hb_forward<T2> (v2).cmp (
hb_forward<T1> (v1)) == 0); }
437 hb_forward<T2> (v2).cmp (hb_forward<T1> (v1)) == 0-> decltype ((hb_forward<T2> (v2).cmp (hb_forward<
T1> (v1)) == 0)) { return (hb_forward<T2> (v2).cmp (
hb_forward<T1> (v1)) == 0); }
438 )-> decltype ((hb_forward<T2> (v2).cmp (hb_forward<
T1> (v1)) == 0)) { return (hb_forward<T2> (v2).cmp (
hb_forward<T1> (v1)) == 0); }
439
440 template <typename T1, typename T2> auto
441 impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN-> decltype ((hb_forward<T1> (v1).cmp (hb_forward<
T2> (v2)) == 0)) { return (hb_forward<T1> (v1).cmp (
hb_forward<T2> (v2)) == 0); }
442 (-> decltype ((hb_forward<T1> (v1).cmp (hb_forward<
T2> (v2)) == 0)) { return (hb_forward<T1> (v1).cmp (
hb_forward<T2> (v2)) == 0); }
443 hb_forward<T1> (v1).cmp (hb_forward<T2> (v2)) == 0-> decltype ((hb_forward<T1> (v1).cmp (hb_forward<
T2> (v2)) == 0)) { return (hb_forward<T1> (v1).cmp (
hb_forward<T2> (v2)) == 0); }
444 )-> decltype ((hb_forward<T1> (v1).cmp (hb_forward<
T2> (v2)) == 0)) { return (hb_forward<T1> (v1).cmp (
hb_forward<T2> (v2)) == 0); }
445
446 template <typename T1, typename T2> auto
447 impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN-> decltype ((hb_forward<T1> (v1) == hb_forward<T2
> (v2))) { return (hb_forward<T1> (v1) == hb_forward
<T2> (v2)); }
448 (-> decltype ((hb_forward<T1> (v1) == hb_forward<T2
> (v2))) { return (hb_forward<T1> (v1) == hb_forward
<T2> (v2)); }
449 hb_forward<T1> (v1) == hb_forward<T2> (v2)-> decltype ((hb_forward<T1> (v1) == hb_forward<T2
> (v2))) { return (hb_forward<T1> (v1) == hb_forward
<T2> (v2)); }
450 )-> decltype ((hb_forward<T1> (v1) == hb_forward<T2
> (v2))) { return (hb_forward<T1> (v1) == hb_forward
<T2> (v2)); }
451
452 public:
453
454 template <typename T1, typename T2> auto
455 operator () (T1&& v1, T2 &&v2) const HB_AUTO_RETURN-> decltype ((impl (hb_forward<T1> (v1), hb_forward<
T2> (v2), hb_priority<16> ()))) { return (impl (hb_forward
<T1> (v1), hb_forward<T2> (v2), hb_priority<16
> ())); }
456 (-> decltype ((impl (hb_forward<T1> (v1), hb_forward<
T2> (v2), hb_priority<16> ()))) { return (impl (hb_forward
<T1> (v1), hb_forward<T2> (v2), hb_priority<16
> ())); }
457 impl (hb_forward<T1> (v1),-> decltype ((impl (hb_forward<T1> (v1), hb_forward<
T2> (v2), hb_priority<16> ()))) { return (impl (hb_forward
<T1> (v1), hb_forward<T2> (v2), hb_priority<16
> ())); }
458 hb_forward<T2> (v2),-> decltype ((impl (hb_forward<T1> (v1), hb_forward<
T2> (v2), hb_priority<16> ()))) { return (impl (hb_forward
<T1> (v1), hb_forward<T2> (v2), hb_priority<16
> ())); }
459 hb_prioritize)-> decltype ((impl (hb_forward<T1> (v1), hb_forward<
T2> (v2), hb_priority<16> ()))) { return (impl (hb_forward
<T1> (v1), hb_forward<T2> (v2), hb_priority<16
> ())); }
460 )-> decltype ((impl (hb_forward<T1> (v1), hb_forward<
T2> (v2), hb_priority<16> ()))) { return (impl (hb_forward
<T1> (v1), hb_forward<T2> (v2), hb_priority<16
> ())); }
461}
462HB_FUNCOBJ (hb_equal)static const hb_equal __attribute__((unused));
463
464
465template <typename T1, typename T2>
466struct hb_pair_t
467{
468 typedef T1 first_t;
469 typedef T2 second_t;
470 typedef hb_pair_t<T1, T2> pair_t;
471
472 hb_pair_t (T1 a, T2 b)hb_pair_t<T1 a, T2 b> : first (a), second (b) {}
473
474 template <typename Q1, typename Q2,
475 hb_enable_if (hb_is_convertible (T1, Q1) &&typename hb_enable_if<(hb_is_convertible<T1, Q1>::value
&& hb_is_convertible<T2, T2>::value)>::type
* = nullptr
476 hb_is_convertible (T2, T2))typename hb_enable_if<(hb_is_convertible<T1, Q1>::value
&& hb_is_convertible<T2, T2>::value)>::type
* = nullptr
>
477 operator hb_pair_t<Q1, Q2> () { return hb_pair_t<Q1, Q2> (first, second); }
478
479 hb_pair_t<T1, T2> reverse () const
480 { return hb_pair_t<T1, T2> (second, first); }
481
482 bool operator == (const pair_t& o) const { return first == o.first && second == o.second; }
483 bool operator != (const pair_t& o) const { return !(*this == o); }
484 bool operator < (const pair_t& o) const { return first < o.first || (first == o.first && second < o.second); }
485 bool operator >= (const pair_t& o) const { return !(*this < o); }
486 bool operator > (const pair_t& o) const { return first > o.first || (first == o.first && second > o.second); }
487 bool operator <= (const pair_t& o) const { return !(*this > o); }
488
489 T1 first;
490 T2 second;
491};
492#define hb_pair_t(T1,T2)hb_pair_t<T1, T2> hb_pair_t<T1, T2>
493template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
494hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
495
496struct
497{
498 template <typename Pair> constexpr typename Pair::first_t
499 operator () (const Pair& pair) const { return pair.first; }
500}
501HB_FUNCOBJ (hb_first)static const hb_first __attribute__((unused));
502
503struct
504{
505 template <typename Pair> constexpr typename Pair::second_t
506 operator () (const Pair& pair) const { return pair.second; }
507}
508HB_FUNCOBJ (hb_second)static const hb_second __attribute__((unused));
509
510/* Note. In min/max impl, we can use hb_type_identity<T> for second argument.
511 * However, that would silently convert between different-signedness integers.
512 * Instead we accept two different types, such that compiler can err if
513 * comparing integers of different signedness. */
514struct
515{
516 template <typename T, typename T2> constexpr auto
517 operator () (T&& a, T2&& b) const HB_AUTO_RETURN-> decltype ((a <= b ? hb_forward<T> (a) : hb_forward
<T2> (b))) { return (a <= b ? hb_forward<T> (a
) : hb_forward<T2> (b)); }
518 (a <= b ? hb_forward<T> (a) : hb_forward<T2> (b))-> decltype ((a <= b ? hb_forward<T> (a) : hb_forward
<T2> (b))) { return (a <= b ? hb_forward<T> (a
) : hb_forward<T2> (b)); }
519}
520HB_FUNCOBJ (hb_min)static const hb_min __attribute__((unused));
521struct
522{
523 template <typename T, typename T2> constexpr auto
524 operator () (T&& a, T2&& b) const HB_AUTO_RETURN-> decltype ((a >= b ? hb_forward<T> (a) : hb_forward
<T2> (b))) { return (a >= b ? hb_forward<T> (a
) : hb_forward<T2> (b)); }
525 (a >= b ? hb_forward<T> (a) : hb_forward<T2> (b))-> decltype ((a >= b ? hb_forward<T> (a) : hb_forward
<T2> (b))) { return (a >= b ? hb_forward<T> (a
) : hb_forward<T2> (b)); }
526}
527HB_FUNCOBJ (hb_max)static const hb_max __attribute__((unused));
528struct
529{
530 template <typename T, typename T2, typename T3> constexpr auto
531 operator () (T&& x, T2&& min, T3&& max) const HB_AUTO_RETURN-> decltype ((hb_min (hb_max (hb_forward<T> (x), hb_forward
<T2> (min)), hb_forward<T3> (max)))) { return (hb_min
(hb_max (hb_forward<T> (x), hb_forward<T2> (min)
), hb_forward<T3> (max))); }
532 (hb_min (hb_max (hb_forward<T> (x), hb_forward<T2> (min)), hb_forward<T3> (max)))-> decltype ((hb_min (hb_max (hb_forward<T> (x), hb_forward
<T2> (min)), hb_forward<T3> (max)))) { return (hb_min
(hb_max (hb_forward<T> (x), hb_forward<T2> (min)
), hb_forward<T3> (max))); }
533}
534HB_FUNCOBJ (hb_clamp)static const hb_clamp __attribute__((unused));
535
536
537/*
538 * Bithacks.
539 */
540
541/* Return the number of 1 bits in v. */
542template <typename T>
543static inline unsigned int
544hb_popcount (T v)
545{
546#if (defined(__GNUC__4) && (__GNUC__4 >= 4)) || defined(__clang__1)
547 if (sizeof (T) <= sizeof (unsigned int))
548 return __builtin_popcount (v);
549
550 if (sizeof (T) <= sizeof (unsigned long))
551 return __builtin_popcountl (v);
552
553 if (sizeof (T) <= sizeof (unsigned long long))
554 return __builtin_popcountll (v);
555#endif
556
557 if (sizeof (T) <= 4)
558 {
559 /* "HACKMEM 169" */
560 uint32_t y;
561 y = (v >> 1) &033333333333;
562 y = v - y - ((y >>1) & 033333333333);
563 return (((y + (y >> 3)) & 030707070707) % 077);
564 }
565
566 if (sizeof (T) == 8)
567 {
568 unsigned int shift = 32;
569 return hb_popcount<uint32_t> ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift));
570 }
571
572 if (sizeof (T) == 16)
573 {
574 unsigned int shift = 64;
575 return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
576 }
577
578 assert (0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-algs.hh"
, 578, __extension__ __PRETTY_FUNCTION__))
;
579 return 0; /* Shut up stupid compiler. */
580}
581
582/* Returns the number of bits needed to store number */
583template <typename T>
584static inline unsigned int
585hb_bit_storage (T v)
586{
587 if (unlikely (!v)(__builtin_expect (!!(!v), 0))) return 0;
588
589#if (defined(__GNUC__4) && (__GNUC__4 >= 4)) || defined(__clang__1)
590 if (sizeof (T) <= sizeof (unsigned int))
591 return sizeof (unsigned int) * 8 - __builtin_clz (v);
592
593 if (sizeof (T) <= sizeof (unsigned long))
594 return sizeof (unsigned long) * 8 - __builtin_clzl (v);
595
596 if (sizeof (T) <= sizeof (unsigned long long))
597 return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
598#endif
599
600#if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__4 < 4))
601 if (sizeof (T) <= sizeof (unsigned int))
602 {
603 unsigned long where;
604 _BitScanReverse (&where, v);
605 return 1 + where;
606 }
607# if defined(_WIN64)
608 if (sizeof (T) <= 8)
609 {
610 unsigned long where;
611 _BitScanReverse64 (&where, v);
612 return 1 + where;
613 }
614# endif
615#endif
616
617 if (sizeof (T) <= 4)
618 {
619 /* "bithacks" */
620 const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
621 const unsigned int S[] = {1, 2, 4, 8, 16};
622 unsigned int r = 0;
623 for (int i = 4; i >= 0; i--)
624 if (v & b[i])
625 {
626 v >>= S[i];
627 r |= S[i];
628 }
629 return r + 1;
630 }
631 if (sizeof (T) <= 8)
632 {
633 /* "bithacks" */
634 const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
635 const unsigned int S[] = {1, 2, 4, 8, 16, 32};
636 unsigned int r = 0;
637 for (int i = 5; i >= 0; i--)
638 if (v & b[i])
639 {
640 v >>= S[i];
641 r |= S[i];
642 }
643 return r + 1;
644 }
645 if (sizeof (T) == 16)
646 {
647 unsigned int shift = 64;
648 return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
649 hb_bit_storage<uint64_t> ((uint64_t) v);
650 }
651
652 assert (0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-algs.hh"
, 652, __extension__ __PRETTY_FUNCTION__))
;
653 return 0; /* Shut up stupid compiler. */
654}
655
656/* Returns the number of zero bits in the least significant side of v */
657template <typename T>
658static inline unsigned int
659hb_ctz (T v)
660{
661 if (unlikely (!v)(__builtin_expect (!!(!v), 0))) return 8 * sizeof (T);
662
663#if (defined(__GNUC__4) && (__GNUC__4 >= 4)) || defined(__clang__1)
664 if (sizeof (T) <= sizeof (unsigned int))
665 return __builtin_ctz (v);
666
667 if (sizeof (T) <= sizeof (unsigned long))
668 return __builtin_ctzl (v);
669
670 if (sizeof (T) <= sizeof (unsigned long long))
671 return __builtin_ctzll (v);
672#endif
673
674#if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__4 < 4))
675 if (sizeof (T) <= sizeof (unsigned int))
676 {
677 unsigned long where;
678 _BitScanForward (&where, v);
679 return where;
680 }
681# if defined(_WIN64)
682 if (sizeof (T) <= 8)
683 {
684 unsigned long where;
685 _BitScanForward64 (&where, v);
686 return where;
687 }
688# endif
689#endif
690
691 if (sizeof (T) <= 4)
692 {
693 /* "bithacks" */
694 unsigned int c = 32;
695 v &= - (int32_t) v;
696 if (v) c--;
697 if (v & 0x0000FFFF) c -= 16;
698 if (v & 0x00FF00FF) c -= 8;
699 if (v & 0x0F0F0F0F) c -= 4;
700 if (v & 0x33333333) c -= 2;
701 if (v & 0x55555555) c -= 1;
702 return c;
703 }
704 if (sizeof (T) <= 8)
705 {
706 /* "bithacks" */
707 unsigned int c = 64;
708 v &= - (int64_t) (v);
709 if (v) c--;
710 if (v & 0x00000000FFFFFFFFULL) c -= 32;
711 if (v & 0x0000FFFF0000FFFFULL) c -= 16;
712 if (v & 0x00FF00FF00FF00FFULL) c -= 8;
713 if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
714 if (v & 0x3333333333333333ULL) c -= 2;
715 if (v & 0x5555555555555555ULL) c -= 1;
716 return c;
717 }
718 if (sizeof (T) == 16)
719 {
720 unsigned int shift = 64;
721 return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
722 hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
723 }
724
725 assert (0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-algs.hh"
, 725, __extension__ __PRETTY_FUNCTION__))
;
726 return 0; /* Shut up stupid compiler. */
727}
728
729
730/*
731 * Tiny stuff.
732 */
733
734/* ASCII tag/character handling */
735static inline bool ISALPHA (unsigned char c)
736{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
737static inline bool ISALNUM (unsigned char c)
738{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
739static inline bool ISSPACE (unsigned char c)
740{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
741static inline unsigned char TOUPPER (unsigned char c)
742{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
743static inline unsigned char TOLOWER (unsigned char c)
744{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
745static inline bool ISHEX (unsigned char c)
746{ return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); }
747static inline unsigned char TOHEX (uint8_t c)
748{ return (c & 0xF) <= 9 ? (c & 0xF) + '0' : (c & 0xF) + 'a' - 10; }
749static inline uint8_t FROMHEX (unsigned char c)
750{ return (c >= '0' && c <= '9') ? c - '0' : TOLOWER (c) - 'a' + 10; }
751
752static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
753{ return (a + (b - 1)) / b; }
754
755
756#undef ARRAY_LENGTH
757template <typename Type, unsigned int n>
758static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
759/* A const version, but does not detect erratically being called on pointers. */
760#define ARRAY_LENGTH_CONST(__array)((signed int) (sizeof (__array) / sizeof (__array[0]))) ((signed int) (sizeof (__array) / sizeof (__array[0])))
761
762
763static inline int
764hb_memcmp (const void *a, const void *b, unsigned int len)
765{
766 /* It's illegal to pass NULL to memcmp(), even if len is zero.
767 * So, wrap it.
768 * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
769 if (unlikely (!len)(__builtin_expect (!!(!len), 0))) return 0;
770 return memcmp (a, b, len);
771}
772
773static inline void *
774hb_memset (void *s, int c, unsigned int n)
775{
776 /* It's illegal to pass NULL to memset(), even if n is zero. */
777 if (unlikely (!n)(__builtin_expect (!!(!n), 0))) return 0;
778 return memset (s, c, n);
779}
780
781static inline unsigned int
782hb_ceil_to_4 (unsigned int v)
783{
784 return ((v - 1) | 3) + 1;
785}
786
787template <typename T> static inline bool
788hb_in_range (T u, T lo, T hi)
789{
790 static_assert (!hb_is_signed<T>::value, "");
791
792 /* The casts below are important as if T is smaller than int,
793 * the subtract results will become a signed int! */
794 return (T)(u - lo) <= (T)(hi - lo);
795}
796template <typename T> static inline bool
797hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
798{
799 return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
800}
801template <typename T> static inline bool
802hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
803{
804 return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
805}
806
807
808/*
809 * Overflow checking.
810 */
811
812/* Consider __builtin_mul_overflow use here also */
813static inline bool
814hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
815{
816 return (size > 0) && (count >= ((unsigned int) -1) / size);
817}
818
819
820/*
821 * Sort and search.
822 */
823
824template <typename K, typename V, typename ...Ts>
825static int
826_hb_cmp_method (const void *pkey, const void *pval, Ts... ds)
827{
828 const K& key = * (const K*) pkey;
829 const V& val = * (const V*) pval;
830
831 return val.cmp (key, ds...);
832}
833
834template <typename V, typename K, typename ...Ts>
835static inline bool
836hb_bsearch_impl (unsigned *pos, /* Out */
837 const K& key,
838 V* base, size_t nmemb, size_t stride,
839 int (*compar)(const void *_key, const void *_item, Ts... _ds),
840 Ts... ds)
841{
842 /* This is our *only* bsearch implementation. */
843
844 int min = 0, max = (int) nmemb - 1;
845 while (min <= max)
846 {
847 int mid = ((unsigned int) min + (unsigned int) max) / 2;
848#pragma GCC diagnostic push
849#pragma GCC diagnostic ignored "-Wcast-align"
850 V* p = (V*) (((const char *) base) + (mid * stride));
851#pragma GCC diagnostic pop
852 int c = compar ((const void *) hb_addressof (key), (const void *) p, ds...);
853 if (c < 0)
854 max = mid - 1;
855 else if (c > 0)
856 min = mid + 1;
857 else
858 {
859 *pos = mid;
860 return true;
861 }
862 }
863 *pos = min;
864 return false;
865}
866
867template <typename V, typename K>
868static inline V*
869hb_bsearch (const K& key, V* base,
870 size_t nmemb, size_t stride = sizeof (V),
871 int (*compar)(const void *_key, const void *_item) = _hb_cmp_method<K, V>)
872{
873 unsigned pos;
874#pragma GCC diagnostic push
875#pragma GCC diagnostic ignored "-Wcast-align"
876 return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar) ?
877 (V*) (((const char *) base) + (pos * stride)) : nullptr;
878#pragma GCC diagnostic pop
879}
880template <typename V, typename K, typename ...Ts>
881static inline V*
882hb_bsearch (const K& key, V* base,
883 size_t nmemb, size_t stride,
884 int (*compar)(const void *_key, const void *_item, Ts... _ds),
885 Ts... ds)
886{
887 unsigned pos;
888#pragma GCC diagnostic push
889#pragma GCC diagnostic ignored "-Wcast-align"
890 return hb_bsearch_impl (&pos, key, base, nmemb, stride, compar, ds...) ?
891 (V*) (((const char *) base) + (pos * stride)) : nullptr;
892#pragma GCC diagnostic pop
893}
894
895
896/* From https://github.com/noporpoise/sort_r
897 Feb 5, 2019 (c8c65c1e)
898 Modified to support optional argument using templates */
899
900/* Isaac Turner 29 April 2014 Public Domain */
901
902/*
903hb_qsort function to be exported.
904Parameters:
905 base is the array to be sorted
906 nel is the number of elements in the array
907 width is the size in bytes of each element of the array
908 compar is the comparison function
909 arg (optional) is a pointer to be passed to the comparison function
910
911void hb_qsort(void *base, size_t nel, size_t width,
912 int (*compar)(const void *_a, const void *_b, [void *_arg]),
913 [void *arg]);
914*/
915
916#define SORT_R_SWAP(a,b,tmp)((tmp) = (a), (a) = (b), (b) = (tmp)) ((tmp) = (a), (a) = (b), (b) = (tmp))
917
918/* swap a and b */
919/* a and b must not be equal! */
920static inline void sort_r_swap(char *__restrict a, char *__restrict b,
921 size_t w)
922{
923 char tmp, *end = a+w;
924 for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp)((tmp) = (*a), (*a) = (*b), (*b) = (tmp)); }
26
Loop condition is true. Entering loop body
27
Loop condition is true. Entering loop body
28
Assigned value is garbage or undefined
925}
926
927/* swap a, b iff a>b */
928/* a and b must not be equal! */
929/* __restrict is same as restrict but better support on old machines */
930template <typename ...Ts>
931static inline int sort_r_cmpswap(char *__restrict a,
932 char *__restrict b, size_t w,
933 int (*compar)(const void *_a,
934 const void *_b,
935 Ts... _ds),
936 Ts... ds)
937{
938 if(compar(a, b, ds...) > 0) {
23
Assuming the condition is true
24
Taking true branch
939 sort_r_swap(a, b, w);
25
Calling 'sort_r_swap'
940 return 1;
941 }
942 return 0;
943}
944
945/*
946Swap consecutive blocks of bytes of size na and nb starting at memory addr ptr,
947with the smallest swap so that the blocks are in the opposite order. Blocks may
948be internally re-ordered e.g.
949 12345ab -> ab34512
950 123abc -> abc123
951 12abcde -> deabc12
952*/
953static inline void sort_r_swap_blocks(char *ptr, size_t na, size_t nb)
954{
955 if(na > 0 && nb > 0) {
956 if(na > nb) { sort_r_swap(ptr, ptr+na, nb); }
957 else { sort_r_swap(ptr, ptr+nb, na); }
958 }
959}
960
961/* Implement recursive quicksort ourselves */
962/* Note: quicksort is not stable, equivalent values may be swapped */
963template <typename ...Ts>
964static inline void sort_r_simple(void *base, size_t nel, size_t w,
965 int (*compar)(const void *_a,
966 const void *_b,
967 Ts... _ds),
968 Ts... ds)
969{
970 char *b = (char *)base, *end = b + nel*w;
971
972 /* for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
973 printf("\n"); */
974
975 if(nel
19.1
'nel' is < 10
19.1
'nel' is < 10
19.1
'nel' is < 10
< 10) {
20
Taking true branch
976 /* Insertion sort for arbitrarily small inputs */
977 char *pi, *pj;
978 for(pi = b+w; pi < end; pi += w) {
21
Loop condition is true. Entering loop body
979 for(pj = pi; pj
21.1
'pj' is > 'b'
21.1
'pj' is > 'b'
21.1
'pj' is > 'b'
> b && sort_r_cmpswap(pj-w,pj,w,compar,ds...); pj -= w) {}
22
Calling 'sort_r_cmpswap<void *>'
980 }
981 }
982 else
983 {
984 /* nel > 9; Quicksort */
985
986 int cmp;
987 char *pl, *ple, *pr, *pre, *pivot;
988 char *last = b+w*(nel-1), *tmp;
989
990 /*
991 Use median of second, middle and second-last items as pivot.
992 First and last may have been swapped with pivot and therefore be extreme
993 */
994 char *l[3];
995 l[0] = b + w;
996 l[1] = b+w*(nel/2);
997 l[2] = last - w;
998
999 /* printf("pivots: %i, %i, %i\n", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */
1000
1001 if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp)((tmp) = (l[0]), (l[0]) = (l[1]), (l[1]) = (tmp)); }
1002 if(compar(l[1],l[2],ds...) > 0) {
1003 SORT_R_SWAP(l[1], l[2], tmp)((tmp) = (l[1]), (l[1]) = (l[2]), (l[2]) = (tmp));
1004 if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp)((tmp) = (l[0]), (l[0]) = (l[1]), (l[1]) = (tmp)); }
1005 }
1006
1007 /* swap mid value (l[1]), and last element to put pivot as last element */
1008 if(l[1] != last) { sort_r_swap(l[1], last, w); }
1009
1010 /*
1011 pl is the next item on the left to be compared to the pivot
1012 pr is the last item on the right that was compared to the pivot
1013 ple is the left position to put the next item that equals the pivot
1014 ple is the last right position where we put an item that equals the pivot
1015 v- end (beyond the array)
1016 EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE.
1017 ^- b ^- ple ^- pl ^- pr ^- pre ^- last (where the pivot is)
1018 Pivot comparison key:
1019 E = equal, L = less than, u = unknown, G = greater than, E = equal
1020 */
1021 pivot = last;
1022 ple = pl = b;
1023 pre = pr = last;
1024
1025 /*
1026 Strategy:
1027 Loop into the list from the left and right at the same time to find:
1028 - an item on the left that is greater than the pivot
1029 - an item on the right that is less than the pivot
1030 Once found, they are swapped and the loop continues.
1031 Meanwhile items that are equal to the pivot are moved to the edges of the
1032 array.
1033 */
1034 while(pl < pr) {
1035 /* Move left hand items which are equal to the pivot to the far left.
1036 break when we find an item that is greater than the pivot */
1037 for(; pl < pr; pl += w) {
1038 cmp = compar(pl, pivot, ds...);
1039 if(cmp > 0) { break; }
1040 else if(cmp == 0) {
1041 if(ple < pl) { sort_r_swap(ple, pl, w); }
1042 ple += w;
1043 }
1044 }
1045 /* break if last batch of left hand items were equal to pivot */
1046 if(pl >= pr) { break; }
1047 /* Move right hand items which are equal to the pivot to the far right.
1048 break when we find an item that is less than the pivot */
1049 for(; pl < pr; ) {
1050 pr -= w; /* Move right pointer onto an unprocessed item */
1051 cmp = compar(pr, pivot, ds...);
1052 if(cmp == 0) {
1053 pre -= w;
1054 if(pr < pre) { sort_r_swap(pr, pre, w); }
1055 }
1056 else if(cmp < 0) {
1057 if(pl < pr) { sort_r_swap(pl, pr, w); }
1058 pl += w;
1059 break;
1060 }
1061 }
1062 }
1063
1064 pl = pr; /* pr may have gone below pl */
1065
1066 /*
1067 Now we need to go from: EEELLLGGGGEEEE
1068 to: LLLEEEEEEEGGGG
1069 Pivot comparison key:
1070 E = equal, L = less than, u = unknown, G = greater than, E = equal
1071 */
1072 sort_r_swap_blocks(b, ple-b, pl-ple);
1073 sort_r_swap_blocks(pr, pre-pr, end-pre);
1074
1075 /*for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
1076 printf("\n");*/
1077
1078 sort_r_simple(b, (pl-ple)/w, w, compar, ds...);
1079 sort_r_simple(end-(pre-pr), (pre-pr)/w, w, compar, ds...);
1080 }
1081}
1082
1083static inline void
1084hb_qsort (void *base, size_t nel, size_t width,
1085 int (*compar)(const void *_a, const void *_b))
1086{
1087#if defined(__OPTIMIZE_SIZE__) && !defined(HB_USE_INTERNAL_QSORT)
1088 qsort (base, nel, width, compar);
1089#else
1090 sort_r_simple (base, nel, width, compar);
1091#endif
1092}
1093
1094static inline void
1095hb_qsort (void *base, size_t nel, size_t width,
1096 int (*compar)(const void *_a, const void *_b, void *_arg),
1097 void *arg)
1098{
1099#ifdef HAVE_GNU_QSORT_R
1100 qsort_r (base, nel, width, compar, arg);
1101#else
1102 sort_r_simple (base, nel, width, compar, arg);
19
Calling 'sort_r_simple<void *>'
1103#endif
1104}
1105
1106
1107template <typename T, typename T2, typename T3> static inline void
1108hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2)
1109{
1110 for (unsigned int i = 1; i < len; i++)
1111 {
1112 unsigned int j = i;
1113 while (j && compar (&array[j - 1], &array[i]) > 0)
1114 j--;
1115 if (i == j)
1116 continue;
1117 /* Move item i to occupy place for item j, shift what's in between. */
1118 {
1119 T t = array[i];
1120 memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
1121 array[j] = t;
1122 }
1123 if (array2)
1124 {
1125 T3 t = array2[i];
1126 memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T3));
1127 array2[j] = t;
1128 }
1129 }
1130}
1131
1132template <typename T> static inline void
1133hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
1134{
1135 hb_stable_sort (array, len, compar, (int *) nullptr);
1136}
1137
1138static inline hb_bool_t
1139hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
1140{
1141 unsigned int v;
1142 const char *p = s;
1143 const char *end = p + len;
1144 if (unlikely (!hb_parse_uint (&p, end, &v, true/* whole buffer */, base))(__builtin_expect (!!(!hb_parse_uint (&p, end, &v, true
, base)), 0))
)
1145 return false;
1146
1147 *out = v;
1148 return true;
1149}
1150
1151
1152/* Operators. */
1153
1154struct hb_bitwise_and
1155{ HB_PARTIALIZE(2)template <typename _T> auto operator () (_T&& _v
) const -> decltype ((hb_partial<2> (+this, hb_forward
<_T> (_v)))) { return (hb_partial<2> (+this, hb_forward
<_T> (_v))); } static_assert (true, "")
;
1156 template <typename T> constexpr auto
1157 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)-> decltype ((a & b)) { return (a & b); }
1158}
1159HB_FUNCOBJ (hb_bitwise_and)static const hb_bitwise_and __attribute__((unused));
1160struct hb_bitwise_or
1161{ HB_PARTIALIZE(2)template <typename _T> auto operator () (_T&& _v
) const -> decltype ((hb_partial<2> (+this, hb_forward
<_T> (_v)))) { return (hb_partial<2> (+this, hb_forward
<_T> (_v))); } static_assert (true, "")
;
1162 template <typename T> constexpr auto
1163 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)-> decltype ((a | b)) { return (a | b); }
1164}
1165HB_FUNCOBJ (hb_bitwise_or)static const hb_bitwise_or __attribute__((unused));
1166struct hb_bitwise_xor
1167{ HB_PARTIALIZE(2)template <typename _T> auto operator () (_T&& _v
) const -> decltype ((hb_partial<2> (+this, hb_forward
<_T> (_v)))) { return (hb_partial<2> (+this, hb_forward
<_T> (_v))); } static_assert (true, "")
;
1168 template <typename T> constexpr auto
1169 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)-> decltype ((a ^ b)) { return (a ^ b); }
1170}
1171HB_FUNCOBJ (hb_bitwise_xor)static const hb_bitwise_xor __attribute__((unused));
1172struct hb_bitwise_sub
1173{ HB_PARTIALIZE(2)template <typename _T> auto operator () (_T&& _v
) const -> decltype ((hb_partial<2> (+this, hb_forward
<_T> (_v)))) { return (hb_partial<2> (+this, hb_forward
<_T> (_v))); } static_assert (true, "")
;
1174 template <typename T> constexpr auto
1175 operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)-> decltype ((a & ~b)) { return (a & ~b); }
1176}
1177HB_FUNCOBJ (hb_bitwise_sub)static const hb_bitwise_sub __attribute__((unused));
1178struct
1179{
1180 template <typename T> constexpr auto
1181 operator () (const T &a) const HB_AUTO_RETURN (~a)-> decltype ((~a)) { return (~a); }
1182}
1183HB_FUNCOBJ (hb_bitwise_neg)static const hb_bitwise_neg __attribute__((unused));
1184
1185struct
1186{ HB_PARTIALIZE(2)template <typename _T> auto operator () (_T&& _v
) const -> decltype ((hb_partial<2> (+this, hb_forward
<_T> (_v)))) { return (hb_partial<2> (+this, hb_forward
<_T> (_v))); } static_assert (true, "")
;
1187 template <typename T, typename T2> constexpr auto
1188 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b)-> decltype ((a + b)) { return (a + b); }
1189}
1190HB_FUNCOBJ (hb_add)static const hb_add __attribute__((unused));
1191struct
1192{ HB_PARTIALIZE(2)template <typename _T> auto operator () (_T&& _v
) const -> decltype ((hb_partial<2> (+this, hb_forward
<_T> (_v)))) { return (hb_partial<2> (+this, hb_forward
<_T> (_v))); } static_assert (true, "")
;
1193 template <typename T, typename T2> constexpr auto
1194 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a - b)-> decltype ((a - b)) { return (a - b); }
1195}
1196HB_FUNCOBJ (hb_sub)static const hb_sub __attribute__((unused));
1197struct
1198{ HB_PARTIALIZE(2)template <typename _T> auto operator () (_T&& _v
) const -> decltype ((hb_partial<2> (+this, hb_forward
<_T> (_v)))) { return (hb_partial<2> (+this, hb_forward
<_T> (_v))); } static_assert (true, "")
;
1199 template <typename T, typename T2> constexpr auto
1200 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)-> decltype ((a * b)) { return (a * b); }
1201}
1202HB_FUNCOBJ (hb_mul)static const hb_mul __attribute__((unused));
1203struct
1204{ HB_PARTIALIZE(2)template <typename _T> auto operator () (_T&& _v
) const -> decltype ((hb_partial<2> (+this, hb_forward
<_T> (_v)))) { return (hb_partial<2> (+this, hb_forward
<_T> (_v))); } static_assert (true, "")
;
1205 template <typename T, typename T2> constexpr auto
1206 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a / b)-> decltype ((a / b)) { return (a / b); }
1207}
1208HB_FUNCOBJ (hb_div)static const hb_div __attribute__((unused));
1209struct
1210{ HB_PARTIALIZE(2)template <typename _T> auto operator () (_T&& _v
) const -> decltype ((hb_partial<2> (+this, hb_forward
<_T> (_v)))) { return (hb_partial<2> (+this, hb_forward
<_T> (_v))); } static_assert (true, "")
;
1211 template <typename T, typename T2> constexpr auto
1212 operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a % b)-> decltype ((a % b)) { return (a % b); }
1213}
1214HB_FUNCOBJ (hb_mod)static const hb_mod __attribute__((unused));
1215struct
1216{
1217 template <typename T> constexpr auto
1218 operator () (const T &a) const HB_AUTO_RETURN (+a)-> decltype ((+a)) { return (+a); }
1219}
1220HB_FUNCOBJ (hb_pos)static const hb_pos __attribute__((unused));
1221struct
1222{
1223 template <typename T> constexpr auto
1224 operator () (const T &a) const HB_AUTO_RETURN (-a)-> decltype ((-a)) { return (-a); }
1225}
1226HB_FUNCOBJ (hb_neg)static const hb_neg __attribute__((unused));
1227struct
1228{
1229 template <typename T> constexpr auto
1230 operator () (T &a) const HB_AUTO_RETURN (++a)-> decltype ((++a)) { return (++a); }
1231}
1232HB_FUNCOBJ (hb_inc)static const hb_inc __attribute__((unused));
1233struct
1234{
1235 template <typename T> constexpr auto
1236 operator () (T &a) const HB_AUTO_RETURN (--a)-> decltype ((--a)) { return (--a); }
1237}
1238HB_FUNCOBJ (hb_dec)static const hb_dec __attribute__((unused));
1239
1240
1241/* Compiler-assisted vectorization. */
1242
1243/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
1244 * basically a fixed-size bitset. */
1245template <typename elt_t, unsigned int byte_size>
1246struct hb_vector_size_t
1247{
1248 elt_t& operator [] (unsigned int i) { return v[i]; }
1249 const elt_t& operator [] (unsigned int i) const { return v[i]; }
1250
1251 void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
1252
1253 template <typename Op>
1254 hb_vector_size_t process (const Op& op) const
1255 {
1256 hb_vector_size_t r;
1257 for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
1258 r.v[i] = op (v[i]);
1259 return r;
1260 }
1261 template <typename Op>
1262 hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const
1263 {
1264 hb_vector_size_t r;
1265 for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
1266 r.v[i] = op (v[i], o.v[i]);
1267 return r;
1268 }
1269 hb_vector_size_t operator | (const hb_vector_size_t &o) const
1270 { return process (hb_bitwise_or, o); }
1271 hb_vector_size_t operator & (const hb_vector_size_t &o) const
1272 { return process (hb_bitwise_and, o); }
1273 hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
1274 { return process (hb_bitwise_xor, o); }
1275 hb_vector_size_t operator ~ () const
1276 { return process (hb_bitwise_neg); }
1277
1278 private:
1279 static_assert (0 == byte_size % sizeof (elt_t), "");
1280 elt_t v[byte_size / sizeof (elt_t)];
1281};
1282
1283
1284#endif /* HB_ALGS_HH */