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
13namespace graphite2 {
14
15typedef gr_uint8 uint8;
16typedef gr_uint8 byte;
17typedef gr_uint16 uint16;
18typedef gr_uint32 uint32;
19typedef gr_int8 int8;
20typedef gr_int16 int16;
21typedef gr_int32 int32;
22typedef size_t uintptr;
23
24#ifdef GRAPHITE2_TELEMETRY
25struct 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
45class telemetry::category
46{
47 size_t * _prev;
48public:
49 category(size_t & t) : _prev(_category) { _category = &t; }
50 ~category() { _category = _prev; }
51};
52
53#else
54struct 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
79namespace graphite2 {
80#endif
81
82#if defined(HAVE_BUILTIN_OVERFLOW)
83inline
84bool 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)
88inline
89bool 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
93inline
94bool 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
103template <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
114template <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
122template <typename T>
123inline T min(const T a, const T b)
124{
125 return a < b ? a : b;
126}
127
128template <typename T>
129inline 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