1 | // SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later |
2 | // Copyright 2010, SIL International, All rights reserved. |
3 | |
4 | #pragma once |
5 | |
6 | #include <cstdlib> |
7 | #include "graphite2/Types.h" |
8 | |
9 | #ifdef GRAPHITE2_CUSTOM_HEADER |
10 | #include GRAPHITE2_CUSTOM_HEADER |
11 | #endif |
12 | |
13 | namespace graphite2 { |
14 | |
15 | typedef gr_uint8 uint8; |
16 | typedef gr_uint8 byte; |
17 | typedef gr_uint16 uint16; |
18 | typedef gr_uint32 uint32; |
19 | typedef gr_int8 int8; |
20 | typedef gr_int16 int16; |
21 | typedef gr_int32 int32; |
22 | typedef size_t uintptr; |
23 | |
24 | #ifdef GRAPHITE2_TELEMETRY |
25 | struct telemetry |
26 | { |
27 | class category; |
28 | |
29 | static size_t * _category; |
30 | static void set_category(size_t & t) throw() { _category = &t; } |
31 | static void stop() throw() { _category = 0; } |
32 | static void count_bytes(size_t n) throw() { if (_category) *_category += n; } |
33 | |
34 | size_t misc, |
35 | silf, |
36 | glyph, |
37 | code, |
38 | states, |
39 | starts, |
40 | transitions; |
41 | |
42 | telemetry() : misc(0), silf(0), glyph(0), code(0), states(0), starts(0), transitions(0) {} |
43 | }; |
44 | |
45 | class telemetry::category |
46 | { |
47 | size_t * _prev; |
48 | public: |
49 | category(size_t & t) : _prev(_category) { _category = &t; } |
50 | ~category() { _category = _prev; } |
51 | }; |
52 | |
53 | #else |
54 | struct telemetry {}; |
55 | #endif |
56 | |
57 | // Checked multiplaction to catch overflow or underflow when allocating memory |
58 | #if defined(__has_builtin) |
59 | #if __has_builtin(__builtin_mul_overflow) |
60 | #define HAVE_BUILTIN_OVERFLOW |
61 | #endif |
62 | #elif defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__INTEL_COMPILER) |
63 | #define HAVE_BUILTIN_OVERFLOW |
64 | #endif |
65 | #if defined(__has_include) |
66 | #if __has_include(<intsafe.h>) && !defined(__CYGWIN__) |
67 | #define HAVE_INTSAFE_H |
68 | #endif |
69 | #elif defined(_WIN32) |
70 | #define HAVE_INTSAFE_H |
71 | #endif |
72 | |
73 | // Need to import intsafe into the top level namespace |
74 | #if defined(HAVE_INTSAFE_H) |
75 | } // namespace graphite2 |
76 | |
77 | #include <intsafe.h> |
78 | |
79 | namespace graphite2 { |
80 | #endif |
81 | |
82 | #if defined(HAVE_BUILTIN_OVERFLOW) |
83 | inline |
84 | bool checked_mul(const size_t a, const size_t b, size_t & t) { |
85 | return __builtin_mul_overflow(a, b, &t); |
86 | } |
87 | #elif defined(HAVE_INTSAFE_H) |
88 | inline |
89 | bool checked_mul(const size_t a, const size_t b, size_t & t) { |
90 | return SizeTMult(a, b, &t) == INTSAFE_E_ARITHMETIC_OVERFLOW; |
91 | } |
92 | #else |
93 | inline |
94 | bool checked_mul(const size_t a, const size_t b, size_t & t) { |
95 | t = a*b; |
96 | return (((a | b) & (~size_t(0) << (sizeof(size_t) << 2))) && (t / a != b)); |
97 | } |
98 | #endif |
99 | |
100 | // typesafe wrapper around malloc for simple types |
101 | // use free(pointer) to deallocate |
102 | |
103 | template <typename T> T * gralloc(size_t n) |
104 | { |
105 | size_t total; |
106 | if (checked_mul(n, sizeof(T), total)) |
107 | return 0; |
108 | #ifdef GRAPHITE2_TELEMETRY |
109 | telemetry::count_bytes(total); |
110 | #endif |
111 | return static_cast<T*>(malloc(total)); |
112 | } |
113 | |
114 | template <typename T> T * grzeroalloc(size_t n) |
115 | { |
116 | #ifdef GRAPHITE2_TELEMETRY |
117 | telemetry::count_bytes(sizeof(T) * n); |
118 | #endif |
119 | return static_cast<T*>(calloc(n, sizeof(T))); |
120 | } |
121 | |
122 | template <typename T> |
123 | inline T min(const T a, const T b) |
124 | { |
125 | return a < b ? a : b; |
126 | } |
127 | |
128 | template <typename T> |
129 | inline T max(const T a, const T b) |
130 | { |
131 | return a > b ? a : b; |
132 | } |
133 | |
134 | } // namespace graphite2 |
135 | |
136 | #define CLASS_NEW_DELETE \ |
137 | void * operator new (size_t size){ return gralloc<byte>(size);} \ |
138 | void * operator new (size_t, void * p) throw() { return p; } \ |
139 | void * operator new[] (size_t size) {return gralloc<byte>(size);} \ |
140 | void * operator new[] (size_t, void * p) throw() { return p; } \ |
141 | void operator delete (void * p) throw() { free(p);} \ |
142 | void operator delete (void *, void *) throw() {} \ |
143 | void operator delete[] (void * p)throw() { free(p); } \ |
144 | void operator delete[] (void *, void *) throw() {} |
145 | |
146 | #if defined(__GNUC__) || defined(__clang__) |
147 | #define GR_MAYBE_UNUSED __attribute__((unused)) |
148 | #else |
149 | #define GR_MAYBE_UNUSED |
150 | #endif |
151 | |
152 | #ifndef __has_cpp_attribute |
153 | # define __has_cpp_attribute(x) 0 |
154 | #endif |
155 | |
156 | #if __has_cpp_attribute(clang::fallthrough) |
157 | # define GR_FALLTHROUGH [[clang::fallthrough]] |
158 | #elif __has_cpp_attribute(gnu::fallthrough) |
159 | # define GR_FALLTHROUGH [[gnu::fallthrough]] |
160 | #elif defined(_MSC_VER) |
161 | /* |
162 | * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis): |
163 | * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx |
164 | */ |
165 | #include <sal.h> |
166 | #define GR_FALLTHROUGH __fallthrough |
167 | #elif __GNUC__ >= 7 |
168 | #define GR_FALLTHROUGH __attribute__ ((fallthrough)) |
169 | #else |
170 | #define GR_FALLTHROUGH /* fallthrough */ |
171 | #endif |
172 | |
173 | #ifdef _MSC_VER |
174 | #pragma warning(disable: 4800) |
175 | #pragma warning(disable: 4355) |
176 | #endif |
177 | |