Bug Summary

File:root/firefox-clang/intl/icu/source/common/cmemory.h
Warning:line 494, column 9
The first element of the 2nd argument is undefined
Note:line 494, column 9
Other elements might also be undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name numparse_impl.cpp -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 -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/config/external/icu/i18n -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/config/external/icu/i18n -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D U_I18N_IMPLEMENTATION -D _LIBCPP_DISABLE_DEPRECATION_WARNINGS -D U_USING_ICU_NAMESPACE=0 -D U_NO_DEFAULT_INCLUDE_UTF_HEADERS=1 -D U_HIDE_OBSOLETE_UTF_OLD_H=1 -D UCONFIG_NO_LEGACY_CONVERSION -D UCONFIG_NO_TRANSLITERATION -D UCONFIG_NO_REGULAR_EXPRESSIONS -D UCONFIG_NO_BREAK_ITERATION -D UCONFIG_NO_IDNA -D UCONFIG_NO_MF2 -D UCONFIG_NO_NORMALIZATION -D UCONFIG_NO_COLLATION -D U_CHARSET_IS_UTF8 -D UNISTR_FROM_CHAR_EXPLICIT=explicit -D UNISTR_FROM_STRING_EXPLICIT=explicit -D U_ENABLE_DYLOAD=0 -D U_DEBUG=1 -I /root/firefox-clang/config/external/icu/i18n -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/config/external/icu/i18n -I /root/firefox-clang/intl/icu/source/common -I /root/firefox-clang/mfbt/double-conversion -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -Wno-comma -Wno-implicit-const-int-float-conversion -Wno-macro-redefined -Wno-microsoft-include -Wno-tautological-unsigned-enum-zero-compare -Wno-unreachable-code-loop-increment -Wno-unreachable-code-return -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ /root/firefox-clang/intl/icu/source/i18n/numparse_impl.cpp

/root/firefox-clang/intl/icu/source/common/cmemory.h

1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/*
4******************************************************************************
5*
6* Copyright (C) 1997-2016, International Business Machines
7* Corporation and others. All Rights Reserved.
8*
9******************************************************************************
10*
11* File CMEMORY.H
12*
13* Contains stdlib.h/string.h memory functions
14*
15* @author Bertrand A. Damiba
16*
17* Modification History:
18*
19* Date Name Description
20* 6/20/98 Bertrand Created.
21* 05/03/99 stephen Changed from functions to macros.
22*
23******************************************************************************
24*/
25
26#ifndef CMEMORY_H
27#define CMEMORY_H
28
29#include "unicode/utypes.h"
30
31#include <stddef.h>
32#include <string.h>
33#include "unicode/localpointer.h"
34#include "uassert.h"
35
36#if U_DEBUG1 && defined(UPRV_MALLOC_COUNT)
37#include <stdio.h>
38#endif
39
40// uprv_memcpy and uprv_memmove
41#if defined(__clang__1)
42#define uprv_memcpy(dst, src, size)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (dst != __null) ? void (0) : __assert_fail
("dst != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__)); (static_cast <bool> (src != __null
) ? void (0) : __assert_fail ("src != __null", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); clang
diagnostic pop :: memcpy(dst, src, size); } while (false)
UPRV_BLOCK_MACRO_BEGINdo { \
43 /* Suppress warnings about addresses that will never be NULL */ \
44 _Pragma("clang diagnostic push")clang diagnostic push \
45 _Pragma("clang diagnostic ignored \"-Waddress\"")clang diagnostic ignored "-Waddress" \
46 U_ASSERT(dst != NULL)(static_cast <bool> (dst != __null) ? void (0) : __assert_fail
("dst != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
; \
47 U_ASSERT(src != NULL)(static_cast <bool> (src != __null) ? void (0) : __assert_fail
("src != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
; \
48 _Pragma("clang diagnostic pop")clang diagnostic pop \
49 U_STANDARD_CPP_NAMESPACE:: memcpy(dst, src, size); \
50} UPRV_BLOCK_MACRO_ENDwhile (false)
51#define uprv_memmove(dst, src, size)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (dst != __null) ? void (0) : __assert_fail
("dst != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__)); (static_cast <bool> (src != __null
) ? void (0) : __assert_fail ("src != __null", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); clang
diagnostic pop :: memmove(dst, src, size); } while (false)
UPRV_BLOCK_MACRO_BEGINdo { \
52 /* Suppress warnings about addresses that will never be NULL */ \
53 _Pragma("clang diagnostic push")clang diagnostic push \
54 _Pragma("clang diagnostic ignored \"-Waddress\"")clang diagnostic ignored "-Waddress" \
55 U_ASSERT(dst != NULL)(static_cast <bool> (dst != __null) ? void (0) : __assert_fail
("dst != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
; \
56 U_ASSERT(src != NULL)(static_cast <bool> (src != __null) ? void (0) : __assert_fail
("src != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
; \
57 _Pragma("clang diagnostic pop")clang diagnostic pop \
58 U_STANDARD_CPP_NAMESPACE:: memmove(dst, src, size); \
59} UPRV_BLOCK_MACRO_ENDwhile (false)
60#elif defined(__GNUC__4)
61#define uprv_memcpy(dst, src, size)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (dst != __null) ? void (0) : __assert_fail
("dst != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__)); (static_cast <bool> (src != __null
) ? void (0) : __assert_fail ("src != __null", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); clang
diagnostic pop :: memcpy(dst, src, size); } while (false)
UPRV_BLOCK_MACRO_BEGINdo { \
62 /* Suppress warnings about addresses that will never be NULL */ \
63 _Pragma("GCC diagnostic push")GCC diagnostic push \
64 _Pragma("GCC diagnostic ignored \"-Waddress\"")GCC diagnostic ignored "-Waddress" \
65 U_ASSERT(dst != NULL)(static_cast <bool> (dst != __null) ? void (0) : __assert_fail
("dst != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
; \
66 U_ASSERT(src != NULL)(static_cast <bool> (src != __null) ? void (0) : __assert_fail
("src != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
; \
67 _Pragma("GCC diagnostic pop")GCC diagnostic pop \
68 U_STANDARD_CPP_NAMESPACE:: memcpy(dst, src, size); \
69} UPRV_BLOCK_MACRO_ENDwhile (false)
70#define uprv_memmove(dst, src, size)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (dst != __null) ? void (0) : __assert_fail
("dst != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__)); (static_cast <bool> (src != __null
) ? void (0) : __assert_fail ("src != __null", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); clang
diagnostic pop :: memmove(dst, src, size); } while (false)
UPRV_BLOCK_MACRO_BEGINdo { \
71 /* Suppress warnings about addresses that will never be NULL */ \
72 _Pragma("GCC diagnostic push")GCC diagnostic push \
73 _Pragma("GCC diagnostic ignored \"-Waddress\"")GCC diagnostic ignored "-Waddress" \
74 U_ASSERT(dst != NULL)(static_cast <bool> (dst != __null) ? void (0) : __assert_fail
("dst != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
; \
75 U_ASSERT(src != NULL)(static_cast <bool> (src != __null) ? void (0) : __assert_fail
("src != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
; \
76 _Pragma("GCC diagnostic pop")GCC diagnostic pop \
77 U_STANDARD_CPP_NAMESPACE:: memmove(dst, src, size); \
78} UPRV_BLOCK_MACRO_ENDwhile (false)
79#else
80#define uprv_memcpy(dst, src, size)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (dst != __null) ? void (0) : __assert_fail
("dst != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__)); (static_cast <bool> (src != __null
) ? void (0) : __assert_fail ("src != __null", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); clang
diagnostic pop :: memcpy(dst, src, size); } while (false)
UPRV_BLOCK_MACRO_BEGINdo { \
81 U_ASSERT(dst != NULL)(static_cast <bool> (dst != __null) ? void (0) : __assert_fail
("dst != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
; \
82 U_ASSERT(src != NULL)(static_cast <bool> (src != __null) ? void (0) : __assert_fail
("src != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
; \
83 U_STANDARD_CPP_NAMESPACE:: memcpy(dst, src, size); \
84} UPRV_BLOCK_MACRO_ENDwhile (false)
85#define uprv_memmove(dst, src, size)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (dst != __null) ? void (0) : __assert_fail
("dst != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__)); (static_cast <bool> (src != __null
) ? void (0) : __assert_fail ("src != __null", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); clang
diagnostic pop :: memmove(dst, src, size); } while (false)
UPRV_BLOCK_MACRO_BEGINdo { \
86 U_ASSERT(dst != NULL)(static_cast <bool> (dst != __null) ? void (0) : __assert_fail
("dst != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
; \
87 U_ASSERT(src != NULL)(static_cast <bool> (src != __null) ? void (0) : __assert_fail
("src != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
; \
88 U_STANDARD_CPP_NAMESPACE:: memmove(dst, src, size); \
89} UPRV_BLOCK_MACRO_ENDwhile (false)
90#endif
91
92/**
93 * \def UPRV_LENGTHOF
94 * Convenience macro to determine the length of a fixed array at compile-time.
95 * @param array A fixed length array
96 * @return The length of the array, in elements
97 * @internal
98 */
99#define UPRV_LENGTHOF(array)(int32_t)(sizeof(array)/sizeof((array)[0])) (int32_t)(sizeof(array)/sizeof((array)[0]))
100#define uprv_memset(buffer, mark, size):: memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE:: memset(buffer, mark, size)
101#define uprv_memcmp(buffer1, buffer2, size):: memcmp(buffer1, buffer2,size) U_STANDARD_CPP_NAMESPACE:: memcmp(buffer1, buffer2,size)
102#define uprv_memchr(ptr, value, num):: memchr(ptr, value, num) U_STANDARD_CPP_NAMESPACE:: memchr(ptr, value, num)
103
104U_CAPIextern "C" void * U_EXPORT2
105uprv_malloc(size_t s) U_MALLOC_ATTR__attribute__ ((__malloc__)) U_ALLOC_SIZE_ATTR(1)__attribute__ ((alloc_size(1)));
106
107U_CAPIextern "C" void * U_EXPORT2
108uprv_realloc(void *mem, size_t size) U_ALLOC_SIZE_ATTR(2)__attribute__ ((alloc_size(2)));
109
110U_CAPIextern "C" void U_EXPORT2
111uprv_free(void *mem);
112
113U_CAPIextern "C" void * U_EXPORT2
114uprv_calloc(size_t num, size_t size) U_MALLOC_ATTR__attribute__ ((__malloc__)) U_ALLOC_SIZE_ATTR2(1,2)__attribute__ ((alloc_size(1,2)));
115
116/**
117 * Get the least significant bits of a pointer (a memory address).
118 * For example, with a mask of 3, the macro gets the 2 least significant bits,
119 * which will be 0 if the pointer is 32-bit (4-byte) aligned.
120 *
121 * uintptr_t is the most appropriate integer type to cast to.
122 */
123#define U_POINTER_MASK_LSB(ptr, mask)((uintptr_t)(ptr) & (mask)) ((uintptr_t)(ptr) & (mask))
124
125/**
126 * Create & return an instance of "type" in statically allocated storage.
127 * e.g.
128 * static std::mutex *myMutex = STATIC_NEW(std::mutex);
129 * To destroy an object created in this way, invoke the destructor explicitly, e.g.
130 * myMutex->~mutex();
131 * DO NOT use delete.
132 * DO NOT use with class UMutex, which has specific support for static instances.
133 *
134 * STATIC_NEW is intended for use when
135 * - We want a static (or global) object.
136 * - We don't want it to ever be destructed, or to explicitly control destruction,
137 * to avoid use-after-destruction problems.
138 * - We want to avoid an ordinary heap allocated object,
139 * to avoid the possibility of memory allocation failures, and
140 * to avoid memory leak reports, from valgrind, for example.
141 * This is defined as a macro rather than a template function because each invocation
142 * must define distinct static storage for the object being returned.
143 */
144#define STATIC_NEW(type)[] () { alignas(type) static char storage[sizeof(type)]; return
new(storage) type();} ()
[] () { \
145 alignas(type) static char storage[sizeof(type)]; \
146 return new(storage) type();} ()
147
148/**
149 * Heap clean up function, called from u_cleanup()
150 * Clears any user heap functions from u_setMemoryFunctions()
151 * Does NOT deallocate any remaining allocated memory.
152 */
153U_CFUNCextern "C" UBool
154cmemory_cleanup(void);
155
156/**
157 * A function called by <TT>uhash_remove</TT>,
158 * <TT>uhash_close</TT>, or <TT>uhash_put</TT> to delete
159 * an existing key or value.
160 * @param obj A key or value stored in a hashtable
161 * @see uprv_deleteUObject
162 */
163typedef void U_CALLCONV UObjectDeleter(void* obj);
164
165/**
166 * Deleter for UObject instances.
167 * Works for all subclasses of UObject because it has a virtual destructor.
168 */
169U_CAPIextern "C" void U_EXPORT2
170uprv_deleteUObject(void *obj);
171
172#ifdef __cplusplus202002L
173
174#include <utility>
175#include "unicode/uobject.h"
176
177U_NAMESPACE_BEGINnamespace icu_78 {
178
179/**
180 * "Smart pointer" class, deletes memory via uprv_free().
181 * For most methods see the LocalPointerBase base class.
182 * Adds operator[] for array item access.
183 *
184 * @see LocalPointerBase
185 */
186template<typename T>
187class LocalMemory : public LocalPointerBase<T> {
188public:
189 using LocalPointerBase<T>::operator*;
190 using LocalPointerBase<T>::operator->;
191 /**
192 * Constructor takes ownership.
193 * @param p simple pointer to an array of T items that is adopted
194 */
195 explicit LocalMemory(T *p=nullptr) : LocalPointerBase<T>(p) {}
196 /**
197 * Move constructor, leaves src with isNull().
198 * @param src source smart pointer
199 */
200 LocalMemory(LocalMemory<T> &&src) noexcept : LocalPointerBase<T>(src.ptr) {
201 src.ptr=nullptr;
202 }
203 /**
204 * Destructor deletes the memory it owns.
205 */
206 ~LocalMemory() {
207 uprv_free(LocalPointerBase<T>::ptr);
208 }
209 /**
210 * Move assignment operator, leaves src with isNull().
211 * The behavior is undefined if *this and src are the same object.
212 * @param src source smart pointer
213 * @return *this
214 */
215 LocalMemory<T> &operator=(LocalMemory<T> &&src) noexcept {
216 uprv_free(LocalPointerBase<T>::ptr);
217 LocalPointerBase<T>::ptr=src.ptr;
218 src.ptr=nullptr;
219 return *this;
220 }
221 /**
222 * Swap pointers.
223 * @param other other smart pointer
224 */
225 void swap(LocalMemory<T> &other) noexcept {
226 T *temp=LocalPointerBase<T>::ptr;
227 LocalPointerBase<T>::ptr=other.ptr;
228 other.ptr=temp;
229 }
230 /**
231 * Non-member LocalMemory swap function.
232 * @param p1 will get p2's pointer
233 * @param p2 will get p1's pointer
234 */
235 friend inline void swap(LocalMemory<T> &p1, LocalMemory<T> &p2) noexcept {
236 p1.swap(p2);
237 }
238 /**
239 * Deletes the array it owns,
240 * and adopts (takes ownership of) the one passed in.
241 * @param p simple pointer to an array of T items that is adopted
242 */
243 void adoptInstead(T *p) {
244 uprv_free(LocalPointerBase<T>::ptr);
245 LocalPointerBase<T>::ptr=p;
246 }
247 /**
248 * Deletes the array it owns, allocates a new one and reset its bytes to 0.
249 * Returns the new array pointer.
250 * If the allocation fails, then the current array is unchanged and
251 * this method returns nullptr.
252 * @param newCapacity must be >0
253 * @return the allocated array pointer, or nullptr if the allocation failed
254 */
255 inline T *allocateInsteadAndReset(int32_t newCapacity=1);
256 /**
257 * Deletes the array it owns and allocates a new one, copying length T items.
258 * Returns the new array pointer.
259 * If the allocation fails, then the current array is unchanged and
260 * this method returns nullptr.
261 * @param newCapacity must be >0
262 * @param length number of T items to be copied from the old array to the new one;
263 * must be no more than the capacity of the old array,
264 * which the caller must track because the LocalMemory does not track it
265 * @return the allocated array pointer, or nullptr if the allocation failed
266 */
267 inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0);
268 /**
269 * Array item access (writable).
270 * No index bounds check.
271 * @param i array index
272 * @return reference to the array item
273 */
274 T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
275};
276
277template<typename T>
278inline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) {
279 if(newCapacity>0) {
280 T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
281 if(p!=nullptr) {
282 uprv_memset(p, 0, newCapacity*sizeof(T)):: memset(p, 0, newCapacity*sizeof(T));
283 uprv_free(LocalPointerBase<T>::ptr);
284 LocalPointerBase<T>::ptr=p;
285 }
286 return p;
287 } else {
288 return nullptr;
289 }
290}
291
292
293template<typename T>
294inline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) {
295 if(newCapacity>0) {
296 T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
297 if(p!=nullptr) {
298 if(length>0) {
299 if(length>newCapacity) {
300 length=newCapacity;
301 }
302 uprv_memcpy(p, LocalPointerBase<T>::ptr, (size_t)length*sizeof(T))do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (p != __null) ? void (0) : __assert_fail
("p != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__)); (static_cast <bool> (LocalPointerBase
<T>::ptr != __null) ? void (0) : __assert_fail ("LocalPointerBase<T>::ptr != __null"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
)); clang diagnostic pop :: memcpy(p, LocalPointerBase<T>
::ptr, (size_t)length*sizeof(T)); } while (false)
;
303 }
304 uprv_free(LocalPointerBase<T>::ptr);
305 LocalPointerBase<T>::ptr=p;
306 }
307 return p;
308 } else {
309 return nullptr;
310 }
311}
312
313/**
314 * Simple array/buffer management class using uprv_malloc() and uprv_free().
315 * Provides an internal array with fixed capacity. Can alias another array
316 * or allocate one.
317 *
318 * The array address is properly aligned for type T. It might not be properly
319 * aligned for types larger than T (or larger than the largest subtype of T).
320 *
321 * Unlike LocalMemory and LocalArray, this class never adopts
322 * (takes ownership of) another array.
323 *
324 * WARNING: MaybeStackArray only works with primitive (plain-old data) types.
325 * It does NOT know how to call a destructor! If you work with classes with
326 * destructors, consider:
327 *
328 * - LocalArray in localpointer.h if you know the length ahead of time
329 * - MaybeStackVector if you know the length at runtime
330 */
331template<typename T, int32_t stackCapacity>
332class MaybeStackArray {
333public:
334 // No heap allocation. Use only on the stack.
335 static void* U_EXPORT2 operator new(size_t) noexcept = delete;
336 static void* U_EXPORT2 operator new[](size_t) noexcept = delete;
337 static void* U_EXPORT2 operator new(size_t, void*) noexcept = delete;
338
339 /**
340 * Default constructor initializes with internal T[stackCapacity] buffer.
341 */
342 MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(false) {}
343 /**
344 * Automatically allocates the heap array if the argument is larger than the stack capacity.
345 * Intended for use when an approximate capacity is known at compile time but the true
346 * capacity is not known until runtime.
347 */
348 MaybeStackArray(int32_t newCapacity, UErrorCode status) : MaybeStackArray() {
349 if (U_FAILURE(status)) {
350 return;
351 }
352 if (capacity < newCapacity) {
353 if (resize(newCapacity) == nullptr) {
354 status = U_MEMORY_ALLOCATION_ERROR;
355 }
356 }
357 }
358 /**
359 * Destructor deletes the array (if owned).
360 */
361 ~MaybeStackArray() { releaseArray(); }
362 /**
363 * Move constructor: transfers ownership or copies the stack array.
364 */
365 MaybeStackArray(MaybeStackArray<T, stackCapacity> &&src) noexcept;
366 /**
367 * Move assignment: transfers ownership or copies the stack array.
368 */
369 MaybeStackArray<T, stackCapacity> &operator=(MaybeStackArray<T, stackCapacity> &&src) noexcept;
370 /**
371 * Returns the array capacity (number of T items).
372 * @return array capacity
373 */
374 int32_t getCapacity() const { return capacity; }
375 /**
376 * Access without ownership change.
377 * @return the array pointer
378 */
379 T *getAlias() const { return ptr; }
380 /**
381 * Returns the array limit. Simple convenience method.
382 * @return getAlias()+getCapacity()
383 */
384 T *getArrayLimit() const { return getAlias()+capacity; }
385 // No "operator T *() const" because that can make
386 // expressions like mbs[index] ambiguous for some compilers.
387 /**
388 * Array item access (const).
389 * No index bounds check.
390 * @param i array index
391 * @return reference to the array item
392 */
393 const T &operator[](ptrdiff_t i) const { return ptr[i]; }
394 /**
395 * Array item access (writable).
396 * No index bounds check.
397 * @param i array index
398 * @return reference to the array item
399 */
400 T &operator[](ptrdiff_t i) { return ptr[i]; }
401 /**
402 * Deletes the array (if owned) and aliases another one, no transfer of ownership.
403 * If the arguments are illegal, then the current array is unchanged.
404 * @param otherArray must not be nullptr
405 * @param otherCapacity must be >0
406 */
407 void aliasInstead(T *otherArray, int32_t otherCapacity) {
408 if(otherArray!=nullptr && otherCapacity>0) {
409 releaseArray();
410 ptr=otherArray;
411 capacity=otherCapacity;
412 needToRelease=false;
413 }
414 }
415 /**
416 * Deletes the array (if owned) and allocates a new one, copying length T items.
417 * Returns the new array pointer.
418 * If the allocation fails, then the current array is unchanged and
419 * this method returns nullptr.
420 * @param newCapacity can be less than or greater than the current capacity;
421 * must be >0
422 * @param length number of T items to be copied from the old array to the new one
423 * @return the allocated array pointer, or nullptr if the allocation failed
424 */
425 inline T *resize(int32_t newCapacity, int32_t length=0);
426 /**
427 * Gives up ownership of the array if owned, or else clones it,
428 * copying length T items; resets itself to the internal stack array.
429 * Returns nullptr if the allocation failed.
430 * @param length number of T items to copy when cloning,
431 * and capacity of the clone when cloning
432 * @param resultCapacity will be set to the returned array's capacity (output-only)
433 * @return the array pointer;
434 * caller becomes responsible for deleting the array
435 */
436 inline T *orphanOrClone(int32_t length, int32_t &resultCapacity);
437
438protected:
439 // Resizes the array to the size of src, then copies the contents of src.
440 void copyFrom(const MaybeStackArray &src, UErrorCode &status) {
441 if (U_FAILURE(status)) {
442 return;
443 }
444 if (this->resize(src.capacity, 0) == nullptr) {
445 status = U_MEMORY_ALLOCATION_ERROR;
446 return;
447 }
448 uprv_memcpy(this->ptr, src.ptr, (size_t)capacity * sizeof(T))do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (this->ptr != __null) ? void (
0) : __assert_fail ("this->ptr != __null", __builtin_FILE (
), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); (static_cast
<bool> (src.ptr != __null) ? void (0) : __assert_fail (
"src.ptr != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__)); clang diagnostic pop :: memcpy(this->
ptr, src.ptr, (size_t)capacity * sizeof(T)); } while (false)
;
449 }
450
451private:
452 T *ptr;
453 int32_t capacity;
454 UBool needToRelease;
455 T stackArray[stackCapacity];
456 void releaseArray() {
457 if(needToRelease) {
458 uprv_free(ptr);
459 }
460 }
461 void resetToStackArray() {
462 ptr=stackArray;
463 capacity=stackCapacity;
464 needToRelease=false;
465 }
466 /* No comparison operators with other MaybeStackArray's. */
467 bool operator==(const MaybeStackArray & /*other*/) = delete;
468 bool operator!=(const MaybeStackArray & /*other*/) = delete;
469 /* No ownership transfer: No copy constructor, no assignment operator. */
470 MaybeStackArray(const MaybeStackArray & /*other*/) = delete;
471 void operator=(const MaybeStackArray & /*other*/) = delete;
472};
473
474template<typename T, int32_t stackCapacity>
475icu::MaybeStackArray<T, stackCapacity>::MaybeStackArray(
476 MaybeStackArray <T, stackCapacity>&& src) noexcept
477 : ptr(src.ptr), capacity(src.capacity), needToRelease(src.needToRelease) {
478 if (src.ptr == src.stackArray) {
479 ptr = stackArray;
480 uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (stackArray != __null) ? void (0)
: __assert_fail ("stackArray != __null", __builtin_FILE (), __builtin_LINE
(), __extension__ __PRETTY_FUNCTION__)); (static_cast <bool
> (src.stackArray != __null) ? void (0) : __assert_fail ("src.stackArray != __null"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
)); clang diagnostic pop :: memcpy(stackArray, src.stackArray
, sizeof(T) * src.capacity); } while (false)
;
481 } else {
482 src.resetToStackArray(); // take ownership away from src
483 }
484}
485
486template<typename T, int32_t stackCapacity>
487inline MaybeStackArray <T, stackCapacity>&
488MaybeStackArray<T, stackCapacity>::operator=(MaybeStackArray <T, stackCapacity>&& src) noexcept {
489 releaseArray(); // in case this instance had its own memory allocated
490 capacity = src.capacity;
491 needToRelease = src.needToRelease;
492 if (src.ptr == src.stackArray) {
20
Assuming field 'ptr' is equal to field 'stackArray'
21
Taking true branch
493 ptr = stackArray;
494 uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (stackArray != __null) ? void (0)
: __assert_fail ("stackArray != __null", __builtin_FILE (), __builtin_LINE
(), __extension__ __PRETTY_FUNCTION__)); (static_cast <bool
> (src.stackArray != __null) ? void (0) : __assert_fail ("src.stackArray != __null"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
)); clang diagnostic pop :: memcpy(stackArray, src.stackArray
, sizeof(T) * src.capacity); } while (false)
;
Other elements might also be undefined
22
'?' condition is true
23
'?' condition is true
24
The first element of the 2nd argument is undefined
495 } else {
496 ptr = src.ptr;
497 src.resetToStackArray(); // take ownership away from src
498 }
499 return *this;
500}
501
502template<typename T, int32_t stackCapacity>
503inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) {
504 if(newCapacity>0) {
505#if U_DEBUG1 && defined(UPRV_MALLOC_COUNT)
506 ::fprintf(::stderrstderr, "MaybeStackArray (resize) alloc %d * %lu\n", newCapacity, sizeof(T));
507#endif
508 T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
509 if(p!=nullptr) {
510 if(length>0) {
511 if(length>capacity) {
512 length=capacity;
513 }
514 if(length>newCapacity) {
515 length=newCapacity;
516 }
517 uprv_memcpy(p, ptr, (size_t)length*sizeof(T))do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (p != __null) ? void (0) : __assert_fail
("p != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__)); (static_cast <bool> (ptr != __null
) ? void (0) : __assert_fail ("ptr != __null", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); clang
diagnostic pop :: memcpy(p, ptr, (size_t)length*sizeof(T));
} while (false)
;
518 }
519 releaseArray();
520 ptr=p;
521 capacity=newCapacity;
522 needToRelease=true;
523 }
524 return p;
525 } else {
526 return nullptr;
527 }
528}
529
530template<typename T, int32_t stackCapacity>
531inline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) {
532 T *p;
533 if(needToRelease) {
534 p=ptr;
535 } else if(length<=0) {
536 return nullptr;
537 } else {
538 if(length>capacity) {
539 length=capacity;
540 }
541 p=(T *)uprv_malloc(length*sizeof(T));
542#if U_DEBUG1 && defined(UPRV_MALLOC_COUNT)
543 ::fprintf(::stderrstderr,"MaybeStacArray (orphan) alloc %d * %lu\n", length,sizeof(T));
544#endif
545 if(p==nullptr) {
546 return nullptr;
547 }
548 uprv_memcpy(p, ptr, (size_t)length*sizeof(T))do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (p != __null) ? void (0) : __assert_fail
("p != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__)); (static_cast <bool> (ptr != __null
) ? void (0) : __assert_fail ("ptr != __null", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); clang
diagnostic pop :: memcpy(p, ptr, (size_t)length*sizeof(T));
} while (false)
;
549 }
550 resultCapacity=length;
551 resetToStackArray();
552 return p;
553}
554
555/**
556 * Variant of MaybeStackArray that allocates a header struct and an array
557 * in one contiguous memory block, using uprv_malloc() and uprv_free().
558 * Provides internal memory with fixed array capacity. Can alias another memory
559 * block or allocate one.
560 * The stackCapacity is the number of T items in the internal memory,
561 * not counting the H header.
562 * Unlike LocalMemory and LocalArray, this class never adopts
563 * (takes ownership of) another memory block.
564 */
565template<typename H, typename T, int32_t stackCapacity>
566class MaybeStackHeaderAndArray {
567public:
568 // No heap allocation. Use only on the stack.
569 static void* U_EXPORT2 operator new(size_t) noexcept = delete;
570 static void* U_EXPORT2 operator new[](size_t) noexcept = delete;
571 static void* U_EXPORT2 operator new(size_t, void*) noexcept = delete;
572
573 /**
574 * Default constructor initializes with internal H+T[stackCapacity] buffer.
575 */
576 MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(false) {}
577 /**
578 * Destructor deletes the memory (if owned).
579 */
580 ~MaybeStackHeaderAndArray() { releaseMemory(); }
581 /**
582 * Returns the array capacity (number of T items).
583 * @return array capacity
584 */
585 int32_t getCapacity() const { return capacity; }
586 /**
587 * Access without ownership change.
588 * @return the header pointer
589 */
590 H *getAlias() const { return ptr; }
591 /**
592 * Returns the array start.
593 * @return array start, same address as getAlias()+1
594 */
595 T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); }
596 /**
597 * Returns the array limit.
598 * @return array limit
599 */
600 T *getArrayLimit() const { return getArrayStart()+capacity; }
601 /**
602 * Access without ownership change. Same as getAlias().
603 * A class instance can be used directly in expressions that take a T *.
604 * @return the header pointer
605 */
606 operator H *() const { return ptr; }
607 /**
608 * Array item access (writable).
609 * No index bounds check.
610 * @param i array index
611 * @return reference to the array item
612 */
613 T &operator[](ptrdiff_t i) { return getArrayStart()[i]; }
614 /**
615 * Deletes the memory block (if owned) and aliases another one, no transfer of ownership.
616 * If the arguments are illegal, then the current memory is unchanged.
617 * @param otherArray must not be nullptr
618 * @param otherCapacity must be >0
619 */
620 void aliasInstead(H *otherMemory, int32_t otherCapacity) {
621 if(otherMemory!=nullptr && otherCapacity>0) {
622 releaseMemory();
623 ptr=otherMemory;
624 capacity=otherCapacity;
625 needToRelease=false;
626 }
627 }
628 /**
629 * Deletes the memory block (if owned) and allocates a new one,
630 * copying the header and length T array items.
631 * Returns the new header pointer.
632 * If the allocation fails, then the current memory is unchanged and
633 * this method returns nullptr.
634 * @param newCapacity can be less than or greater than the current capacity;
635 * must be >0
636 * @param length number of T items to be copied from the old array to the new one
637 * @return the allocated pointer, or nullptr if the allocation failed
638 */
639 inline H *resize(int32_t newCapacity, int32_t length=0);
640 /**
641 * Gives up ownership of the memory if owned, or else clones it,
642 * copying the header and length T array items; resets itself to the internal memory.
643 * Returns nullptr if the allocation failed.
644 * @param length number of T items to copy when cloning,
645 * and array capacity of the clone when cloning
646 * @param resultCapacity will be set to the returned array's capacity (output-only)
647 * @return the header pointer;
648 * caller becomes responsible for deleting the array
649 */
650 inline H *orphanOrClone(int32_t length, int32_t &resultCapacity);
651private:
652 H *ptr;
653 int32_t capacity;
654 UBool needToRelease;
655 // stackHeader must precede stackArray immediately.
656 H stackHeader;
657 T stackArray[stackCapacity];
658 void releaseMemory() {
659 if(needToRelease) {
660 uprv_free(ptr);
661 }
662 }
663 /* No comparison operators with other MaybeStackHeaderAndArray's. */
664 bool operator==(const MaybeStackHeaderAndArray & /*other*/) {return false;}
665 bool operator!=(const MaybeStackHeaderAndArray & /*other*/) {return true;}
666 /* No ownership transfer: No copy constructor, no assignment operator. */
667 MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray & /*other*/) {}
668 void operator=(const MaybeStackHeaderAndArray & /*other*/) {}
669};
670
671template<typename H, typename T, int32_t stackCapacity>
672inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity,
673 int32_t length) {
674 if(newCapacity>=0) {
675#if U_DEBUG1 && defined(UPRV_MALLOC_COUNT)
676 ::fprintf(::stderrstderr,"MaybeStackHeaderAndArray alloc %d + %d * %ul\n", sizeof(H),newCapacity,sizeof(T));
677#endif
678 H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T));
679 if(p!=nullptr) {
680 if(length<0) {
681 length=0;
682 } else if(length>0) {
683 if(length>capacity) {
684 length=capacity;
685 }
686 if(length>newCapacity) {
687 length=newCapacity;
688 }
689 }
690 uprv_memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof(T))do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (p != __null) ? void (0) : __assert_fail
("p != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__)); (static_cast <bool> (ptr != __null
) ? void (0) : __assert_fail ("ptr != __null", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); clang
diagnostic pop :: memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof
(T)); } while (false)
;
691 releaseMemory();
692 ptr=p;
693 capacity=newCapacity;
694 needToRelease=true;
695 }
696 return p;
697 } else {
698 return nullptr;
699 }
700}
701
702template<typename H, typename T, int32_t stackCapacity>
703inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length,
704 int32_t &resultCapacity) {
705 H *p;
706 if(needToRelease) {
707 p=ptr;
708 } else {
709 if(length<0) {
710 length=0;
711 } else if(length>capacity) {
712 length=capacity;
713 }
714#if U_DEBUG1 && defined(UPRV_MALLOC_COUNT)
715 ::fprintf(::stderrstderr,"MaybeStackHeaderAndArray (orphan) alloc %ul + %d * %lu\n", sizeof(H),length,sizeof(T));
716#endif
717 p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T));
718 if(p==nullptr) {
719 return nullptr;
720 }
721 uprv_memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof(T))do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (p != __null) ? void (0) : __assert_fail
("p != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__)); (static_cast <bool> (ptr != __null
) ? void (0) : __assert_fail ("ptr != __null", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); clang
diagnostic pop :: memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof
(T)); } while (false)
;
722 }
723 resultCapacity=length;
724 ptr=&stackHeader;
725 capacity=stackCapacity;
726 needToRelease=false;
727 return p;
728}
729
730/**
731 * A simple memory management class that creates new heap allocated objects (of
732 * any class that has a public constructor), keeps track of them and eventually
733 * deletes them all in its own destructor.
734 *
735 * A typical use-case would be code like this:
736 *
737 * MemoryPool<MyType> pool;
738 *
739 * MyType* o1 = pool.create();
740 * if (o1 != nullptr) {
741 * foo(o1);
742 * }
743 *
744 * MyType* o2 = pool.create(1, 2, 3);
745 * if (o2 != nullptr) {
746 * bar(o2);
747 * }
748 *
749 * // MemoryPool will take care of deleting the MyType objects.
750 *
751 * It doesn't do anything more than that, and is intentionally kept minimalist.
752 */
753template<typename T, int32_t stackCapacity = 8>
754class MemoryPool : public UMemory {
755public:
756 MemoryPool() : fCount(0), fPool() {}
757
758 ~MemoryPool() {
759 for (int32_t i = 0; i < fCount; ++i) {
760 delete fPool[i];
761 }
762 }
763
764 MemoryPool(const MemoryPool&) = delete;
765 MemoryPool& operator=(const MemoryPool&) = delete;
766
767 MemoryPool(MemoryPool&& other) noexcept : fCount(other.fCount),
768 fPool(std::move(other.fPool)) {
769 other.fCount = 0;
770 }
771
772 MemoryPool& operator=(MemoryPool&& other) noexcept {
773 // Since `this` may contain instances that need to be deleted, we can't
774 // just throw them away and replace them with `other`. The normal way of
775 // dealing with this in C++ is to swap `this` and `other`, rather than
776 // simply overwrite: the destruction of `other` can then take care of
777 // running MemoryPool::~MemoryPool() over the still-to-be-deallocated
778 // instances.
779 std::swap(fCount, other.fCount);
780 std::swap(fPool, other.fPool);
18
Calling 'swap<icu_78::MaybeStackArray<icu_78::numparse::impl::CodePointMatcher *, 8>>'
781 return *this;
782 }
783
784 /**
785 * Creates a new object of typename T, by forwarding any and all arguments
786 * to the typename T constructor.
787 *
788 * @param args Arguments to be forwarded to the typename T constructor.
789 * @return A pointer to the newly created object, or nullptr on error.
790 */
791 template<typename... Args>
792 T* create(Args&&... args) {
793 int32_t capacity = fPool.getCapacity();
794 if (fCount == capacity &&
795 fPool.resize(capacity == stackCapacity ? 4 * capacity : 2 * capacity,
796 capacity) == nullptr) {
797 return nullptr;
798 }
799 return fPool[fCount++] = new T(std::forward<Args>(args)...);
800 }
801
802 template <typename... Args>
803 T* createAndCheckErrorCode(UErrorCode &status, Args &&... args) {
804 if (U_FAILURE(status)) {
805 return nullptr;
806 }
807 T *pointer = this->create(args...);
808 if (U_SUCCESS(status) && pointer == nullptr) {
809 status = U_MEMORY_ALLOCATION_ERROR;
810 }
811 return pointer;
812 }
813
814 /**
815 * @return Number of elements that have been allocated.
816 */
817 int32_t count() const {
818 return fCount;
819 }
820
821protected:
822 int32_t fCount;
823 MaybeStackArray<T*, stackCapacity> fPool;
824};
825
826/**
827 * An internal Vector-like implementation based on MemoryPool.
828 *
829 * Heap-allocates each element and stores pointers.
830 *
831 * To append an item to the vector, use emplaceBack.
832 *
833 * MaybeStackVector<MyType> vector;
834 * MyType* element = vector.emplaceBack();
835 * if (!element) {
836 * status = U_MEMORY_ALLOCATION_ERROR;
837 * }
838 * // do stuff with element
839 *
840 * To loop over the vector, use a for loop with indices:
841 *
842 * for (int32_t i = 0; i < vector.length(); i++) {
843 * MyType* element = vector[i];
844 * }
845 */
846template<typename T, int32_t stackCapacity = 8>
847class MaybeStackVector : protected MemoryPool<T, stackCapacity> {
848public:
849 template<typename... Args>
850 T* emplaceBack(Args&&... args) {
851 return this->create(args...);
852 }
853
854 template <typename... Args>
855 T *emplaceBackAndCheckErrorCode(UErrorCode &status, Args &&... args) {
856 return this->createAndCheckErrorCode(status, args...);
857 }
858
859 int32_t length() const {
860 return this->fCount;
861 }
862
863 T** getAlias() {
864 return this->fPool.getAlias();
865 }
866
867 const T *const *getAlias() const {
868 return this->fPool.getAlias();
869 }
870
871 /**
872 * Array item access (read-only).
873 * No index bounds check.
874 * @param i array index
875 * @return reference to the array item
876 */
877 const T* operator[](ptrdiff_t i) const {
878 return this->fPool[i];
879 }
880
881 /**
882 * Array item access (writable).
883 * No index bounds check.
884 * @param i array index
885 * @return reference to the array item
886 */
887 T* operator[](ptrdiff_t i) {
888 return this->fPool[i];
889 }
890};
891
892
893U_NAMESPACE_END}
894
895#endif /* __cplusplus */
896#endif /* CMEMORY_H */

/root/firefox-clang/intl/icu/source/i18n/numparse_impl.cpp

1// © 2018 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3
4#include "unicode/utypes.h"
5
6#if !UCONFIG_NO_FORMATTING0
7
8// Allow implicit conversion from char16_t* to UnicodeString for this file:
9// Helpful in toString methods and elsewhere.
10#define UNISTR_FROM_STRING_EXPLICIT
11
12#include <typeinfo>
13#include <array>
14#include "number_types.h"
15#include "number_patternstring.h"
16#include "numparse_types.h"
17#include "numparse_impl.h"
18#include "numparse_symbols.h"
19#include "numparse_decimal.h"
20#include "unicode/numberformatter.h"
21#include "cstr.h"
22#include "number_mapper.h"
23#include "static_unicode_sets.h"
24
25using namespace icu;
26using namespace icu::number;
27using namespace icu::number::impl;
28using namespace icu::numparse;
29using namespace icu::numparse::impl;
30
31
32NumberParseMatcher::~NumberParseMatcher() = default;
33
34
35NumberParserImpl*
36NumberParserImpl::createSimpleParser(const Locale& locale, const UnicodeString& patternString,
37 parse_flags_t parseFlags, UErrorCode& status) {
38
39 LocalPointer<NumberParserImpl> parser(new NumberParserImpl(parseFlags));
40 DecimalFormatSymbols symbols(locale, status);
41
42 parser->fLocalMatchers.ignorables = {parseFlags};
43 IgnorablesMatcher& ignorables = parser->fLocalMatchers.ignorables;
44
45 DecimalFormatSymbols dfs(locale, status);
46 dfs.setSymbol(DecimalFormatSymbols::kCurrencySymbol, u"IU$");
47 dfs.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, u"ICU");
48 CurrencySymbols currencySymbols({u"ICU", status}, locale, dfs, status);
49
50 ParsedPatternInfo patternInfo;
51 PatternParser::parseToPatternInfo(patternString, patternInfo, status);
52
53 // The following statements set up the affix matchers.
54 AffixTokenMatcherSetupData affixSetupData = {
55 currencySymbols, symbols, ignorables, locale, parseFlags};
56 parser->fLocalMatchers.affixTokenMatcherWarehouse = {&affixSetupData};
57 parser->fLocalMatchers.affixMatcherWarehouse = {&parser->fLocalMatchers.affixTokenMatcherWarehouse};
58 parser->fLocalMatchers.affixMatcherWarehouse.createAffixMatchers(
59 patternInfo, *parser, ignorables, parseFlags, status);
60
61 Grouper grouper = Grouper::forStrategy(UNUM_GROUPING_AUTO);
62 grouper.setLocaleData(patternInfo, locale);
63
64 parser->addMatcher(parser->fLocalMatchers.ignorables);
65 parser->addMatcher(parser->fLocalMatchers.decimal = {symbols, grouper, parseFlags});
66 parser->addMatcher(parser->fLocalMatchers.minusSign = {symbols, false});
67 parser->addMatcher(parser->fLocalMatchers.plusSign = {symbols, false});
68 parser->addMatcher(parser->fLocalMatchers.approximatelySign = {symbols, false});
69 parser->addMatcher(parser->fLocalMatchers.percent = {symbols});
70 parser->addMatcher(parser->fLocalMatchers.permille = {symbols});
71 parser->addMatcher(parser->fLocalMatchers.nan = {symbols});
72 parser->addMatcher(parser->fLocalMatchers.infinity = {symbols});
73 parser->addMatcher(parser->fLocalMatchers.padding = {u"@"});
74 parser->addMatcher(parser->fLocalMatchers.scientific = {symbols, grouper});
75 parser->addMatcher(parser->fLocalMatchers.currency = {currencySymbols, symbols, parseFlags, status});
76 parser->addMatcher(parser->fLocalValidators.number = {});
77
78 parser->freeze();
79 return parser.orphan();
80}
81
82NumberParserImpl*
83NumberParserImpl::createParserFromProperties(const number::impl::DecimalFormatProperties& properties,
84 const DecimalFormatSymbols& symbols, bool parseCurrency,
85 UErrorCode& status) {
86 Locale locale = symbols.getLocale();
87 AutoAffixPatternProvider affixProvider(properties, status);
88 if (U_FAILURE(status)) { return nullptr; }
1
Taking false branch
89 CurrencyUnit currency = resolveCurrency(properties, locale, status);
90 CurrencySymbols currencySymbols(currency, locale, symbols, status);
91 bool isStrict = properties.parseMode.getOrDefault(PARSE_MODE_STRICT) == PARSE_MODE_STRICT;
2
Assuming the condition is false
92 Grouper grouper = Grouper::forProperties(properties);
93 int parseFlags = 0;
94 if (U_FAILURE(status)) { return nullptr; }
3
Taking false branch
95 if (!properties.parseCaseSensitive) {
4
Assuming field 'parseCaseSensitive' is true
5
Taking false branch
96 parseFlags |= PARSE_FLAG_IGNORE_CASE;
97 }
98 if (properties.parseIntegerOnly) {
6
Assuming field 'parseIntegerOnly' is false
7
Taking false branch
99 parseFlags |= PARSE_FLAG_INTEGER_ONLY;
100 }
101 if (properties.signAlwaysShown) {
8
Assuming field 'signAlwaysShown' is false
9
Taking false branch
102 parseFlags |= PARSE_FLAG_PLUS_SIGN_ALLOWED;
103 }
104 if (isStrict
9.1
'isStrict' is false
9.1
'isStrict' is false
9.1
'isStrict' is false
9.1
'isStrict' is false
) {
10
Taking false branch
105 parseFlags |= PARSE_FLAG_STRICT_GROUPING_SIZE;
106 parseFlags |= PARSE_FLAG_STRICT_SEPARATORS;
107 parseFlags |= PARSE_FLAG_USE_FULL_AFFIXES;
108 parseFlags |= PARSE_FLAG_EXACT_AFFIX;
109 parseFlags |= PARSE_FLAG_STRICT_IGNORABLES;
110 } else {
111 parseFlags |= PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES;
112 }
113 if (grouper.getPrimary() <= 0) {
11
Assuming the condition is false
114 parseFlags |= PARSE_FLAG_GROUPING_DISABLED;
115 }
116 if (parseCurrency || affixProvider.get().hasCurrencySign()) {
12
Assuming 'parseCurrency' is false
13
Assuming the condition is false
14
Taking false branch
117 parseFlags |= PARSE_FLAG_MONETARY_SEPARATORS;
118 }
119 if (!parseCurrency
14.1
'parseCurrency' is false
14.1
'parseCurrency' is false
14.1
'parseCurrency' is false
14.1
'parseCurrency' is false
) {
15
Taking true branch
120 parseFlags |= PARSE_FLAG_NO_FOREIGN_CURRENCY;
121 }
122
123 LocalPointer<NumberParserImpl> parser(new NumberParserImpl(parseFlags));
124
125 parser->fLocalMatchers.ignorables = {parseFlags};
126 IgnorablesMatcher& ignorables = parser->fLocalMatchers.ignorables;
127
128 //////////////////////
129 /// AFFIX MATCHERS ///
130 //////////////////////
131
132 // The following statements set up the affix matchers.
133 AffixTokenMatcherSetupData affixSetupData = {
134 currencySymbols, symbols, ignorables, locale, parseFlags};
135 parser->fLocalMatchers.affixTokenMatcherWarehouse = {&affixSetupData};
16
Calling implicit move assignment operator for 'AffixTokenMatcherWarehouse'
17
Calling move assignment operator for 'MemoryPool<icu_78::numparse::impl::CodePointMatcher, 8>'
136 parser->fLocalMatchers.affixMatcherWarehouse = {&parser->fLocalMatchers.affixTokenMatcherWarehouse};
137 parser->fLocalMatchers.affixMatcherWarehouse.createAffixMatchers(
138 affixProvider.get(), *parser, ignorables, parseFlags, status);
139
140 ////////////////////////
141 /// CURRENCY MATCHER ///
142 ////////////////////////
143
144 if (parseCurrency || affixProvider.get().hasCurrencySign()) {
145 parser->addMatcher(parser->fLocalMatchers.currency = {currencySymbols, symbols, parseFlags, status});
146 }
147
148 ///////////////
149 /// PERCENT ///
150 ///////////////
151
152 // ICU-TC meeting, April 11, 2018: accept percent/permille only if it is in the pattern,
153 // and to maintain regressive behavior, divide by 100 even if no percent sign is present.
154 if (!isStrict && affixProvider.get().containsSymbolType(AffixPatternType::TYPE_PERCENT, status)) {
155 parser->addMatcher(parser->fLocalMatchers.percent = {symbols});
156 }
157 if (!isStrict && affixProvider.get().containsSymbolType(AffixPatternType::TYPE_PERMILLE, status)) {
158 parser->addMatcher(parser->fLocalMatchers.permille = {symbols});
159 }
160
161 ///////////////////////////////
162 /// OTHER STANDARD MATCHERS ///
163 ///////////////////////////////
164
165 if (!isStrict) {
166 parser->addMatcher(parser->fLocalMatchers.plusSign = {symbols, false});
167 parser->addMatcher(parser->fLocalMatchers.minusSign = {symbols, false});
168 parser->addMatcher(parser->fLocalMatchers.approximatelySign = {symbols, false});
169 }
170 parser->addMatcher(parser->fLocalMatchers.nan = {symbols});
171 parser->addMatcher(parser->fLocalMatchers.infinity = {symbols});
172 UnicodeString padString = properties.padString;
173 if (!padString.isBogus() && !ignorables.getSet()->contains(padString)) {
174 parser->addMatcher(parser->fLocalMatchers.padding = {padString});
175 }
176 parser->addMatcher(parser->fLocalMatchers.ignorables);
177 parser->addMatcher(parser->fLocalMatchers.decimal = {symbols, grouper, parseFlags});
178 // NOTE: parseNoExponent doesn't disable scientific parsing if we have a scientific formatter
179 if (!properties.parseNoExponent || properties.minimumExponentDigits > 0) {
180 parser->addMatcher(parser->fLocalMatchers.scientific = {symbols, grouper});
181 }
182
183 //////////////////
184 /// VALIDATORS ///
185 //////////////////
186
187 parser->addMatcher(parser->fLocalValidators.number = {});
188 if (isStrict) {
189 parser->addMatcher(parser->fLocalValidators.affix = {});
190 }
191 if (parseCurrency) {
192 parser->addMatcher(parser->fLocalValidators.currency = {});
193 }
194 if (properties.decimalPatternMatchRequired) {
195 bool patternHasDecimalSeparator =
196 properties.decimalSeparatorAlwaysShown || properties.maximumFractionDigits != 0;
197 parser->addMatcher(parser->fLocalValidators.decimalSeparator = {patternHasDecimalSeparator});
198 }
199 // The multiplier takes care of scaling percentages.
200 Scale multiplier = scaleFromProperties(properties);
201 if (multiplier.isValid()) {
202 parser->addMatcher(parser->fLocalValidators.multiplier = {multiplier});
203 }
204
205 parser->freeze();
206 return parser.orphan();
207}
208
209NumberParserImpl::NumberParserImpl(parse_flags_t parseFlags)
210 : fParseFlags(parseFlags) {
211}
212
213NumberParserImpl::~NumberParserImpl() {
214 fNumMatchers = 0;
215}
216
217void NumberParserImpl::addMatcher(NumberParseMatcher& matcher) {
218 if (fNumMatchers + 1 > fMatchers.getCapacity()) {
219 fMatchers.resize(fNumMatchers * 2, fNumMatchers);
220 }
221 fMatchers[fNumMatchers] = &matcher;
222 fNumMatchers++;
223}
224
225void NumberParserImpl::freeze() {
226 fFrozen = true;
227}
228
229parse_flags_t NumberParserImpl::getParseFlags() const {
230 return fParseFlags;
231}
232
233void NumberParserImpl::parse(const UnicodeString& input, bool greedy, ParsedNumber& result,
234 UErrorCode& status) const {
235 return parse(input, 0, greedy, result, status);
236}
237
238void NumberParserImpl::parse(const UnicodeString& input, int32_t start, bool greedy, ParsedNumber& result,
239 UErrorCode& status) const {
240 if (U_FAILURE(status)) {
241 return;
242 }
243 U_ASSERT(fFrozen)(static_cast <bool> (fFrozen) ? void (0) : __assert_fail
("fFrozen", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
;
244 // TODO: Check start >= 0 and start < input.length()
245 StringSegment segment(input, 0 != (fParseFlags & PARSE_FLAG_IGNORE_CASE));
246 segment.adjustOffset(start);
247 if (greedy) {
248 parseGreedy(segment, result, status);
249 } else if (0 != (fParseFlags & PARSE_FLAG_ALLOW_INFINITE_RECURSION)) {
250 // Start at 1 so that recursionLevels never gets to 0
251 parseLongestRecursive(segment, result, 1, status);
252 } else {
253 // Arbitrary recursion safety limit: 100 levels.
254 parseLongestRecursive(segment, result, -100, status);
255 }
256 for (int32_t i = 0; i < fNumMatchers; i++) {
257 fMatchers[i]->postProcess(result);
258 }
259 result.postProcess();
260}
261
262void NumberParserImpl::parseGreedy(StringSegment& segment, ParsedNumber& result,
263 UErrorCode& status) const {
264 // Note: this method is not recursive in order to avoid stack overflow.
265 for (int i = 0; i <fNumMatchers;) {
266 // Base Case
267 if (segment.length() == 0) {
268 return;
269 }
270 const NumberParseMatcher* matcher = fMatchers[i];
271 if (!matcher->smokeTest(segment)) {
272 // Matcher failed smoke test: try the next one
273 i++;
274 continue;
275 }
276 int32_t initialOffset = segment.getOffset();
277 matcher->match(segment, result, status);
278 if (U_FAILURE(status)) {
279 return;
280 }
281 if (segment.getOffset() != initialOffset) {
282 // Greedy heuristic: accept the match and loop back
283 i = 0;
284 continue;
285 } else {
286 // Matcher did not match: try the next one
287 i++;
288 continue;
289 }
290 UPRV_UNREACHABLE_EXITabort();
291 }
292
293 // NOTE: If we get here, the greedy parse completed without consuming the entire string.
294}
295
296void NumberParserImpl::parseLongestRecursive(StringSegment& segment, ParsedNumber& result,
297 int32_t recursionLevels,
298 UErrorCode& status) const {
299 // Base Case
300 if (segment.length() == 0) {
301 return;
302 }
303
304 // Safety against stack overflow
305 if (recursionLevels == 0) {
306 return;
307 }
308
309 // TODO: Give a nice way for the matcher to reset the ParsedNumber?
310 ParsedNumber initial(result);
311 ParsedNumber candidate;
312
313 int initialOffset = segment.getOffset();
314 for (int32_t i = 0; i < fNumMatchers; i++) {
315 const NumberParseMatcher* matcher = fMatchers[i];
316 if (!matcher->smokeTest(segment)) {
317 continue;
318 }
319
320 // In a non-greedy parse, we attempt all possible matches and pick the best.
321 for (int32_t charsToConsume = 0; charsToConsume < segment.length();) {
322 charsToConsume += U16_LENGTH(segment.codePointAt(charsToConsume))((uint32_t)(segment.codePointAt(charsToConsume))<=0xffff ?
1 : 2)
;
323
324 // Run the matcher on a segment of the current length.
325 candidate = initial;
326 segment.setLength(charsToConsume);
327 bool maybeMore = matcher->match(segment, candidate, status);
328 segment.resetLength();
329 if (U_FAILURE(status)) {
330 return;
331 }
332
333 // If the entire segment was consumed, recurse.
334 if (segment.getOffset() - initialOffset == charsToConsume) {
335 parseLongestRecursive(segment, candidate, recursionLevels + 1, status);
336 if (U_FAILURE(status)) {
337 return;
338 }
339 if (candidate.isBetterThan(result)) {
340 result = candidate;
341 }
342 }
343
344 // Since the segment can be re-used, reset the offset.
345 // This does not have an effect if the matcher did not consume any chars.
346 segment.setOffset(initialOffset);
347
348 // Unless the matcher wants to see the next char, continue to the next matcher.
349 if (!maybeMore) {
350 break;
351 }
352 }
353 }
354}
355
356UnicodeString NumberParserImpl::toString() const {
357 UnicodeString result(u"<NumberParserImpl matchers:[");
358 for (int32_t i = 0; i < fNumMatchers; i++) {
359 result.append(u' ');
360 result.append(fMatchers[i]->toString());
361 }
362 result.append(u" ]>", -1);
363 return result;
364}
365
366
367#endif /* #if !UCONFIG_NO_FORMATTING */

/root/firefox-clang/intl/icu/source/i18n/numparse_affixes.h

1// © 2018 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3
4#include "unicode/utypes.h"
5
6#if !UCONFIG_NO_FORMATTING0
7#ifndef __NUMPARSE_AFFIXES_H__
8#define __NUMPARSE_AFFIXES_H__
9
10#include "cmemory.h"
11
12#include "numparse_types.h"
13#include "numparse_symbols.h"
14#include "numparse_currency.h"
15#include "number_affixutils.h"
16#include "number_currencysymbols.h"
17
18U_NAMESPACE_BEGINnamespace icu_78 {
19
20namespace numparse::impl {
21
22// Forward-declaration of implementation classes for friending
23class AffixPatternMatcherBuilder;
24class AffixPatternMatcher;
25
26using ::icu::number::impl::AffixPatternProvider;
27using ::icu::number::impl::TokenConsumer;
28using ::icu::number::impl::CurrencySymbols;
29
30
31class CodePointMatcher : public NumberParseMatcher, public UMemory {
32 public:
33 CodePointMatcher() = default; // WARNING: Leaves the object in an unusable state
34
35 CodePointMatcher(UChar32 cp);
36
37 bool match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const override;
38
39 bool smokeTest(const StringSegment& segment) const override;
40
41 UnicodeString toString() const override;
42
43 private:
44 UChar32 fCp;
45};
46
47
48struct AffixTokenMatcherSetupData {
49 const CurrencySymbols& currencySymbols;
50 const DecimalFormatSymbols& dfs;
51 IgnorablesMatcher& ignorables;
52 const Locale& locale;
53 parse_flags_t parseFlags;
54};
55
56
57/**
58 * Small helper class that generates matchers for individual tokens for AffixPatternMatcher.
59 *
60 * In Java, this is called AffixTokenMatcherFactory (a "factory"). However, in C++, it is called a
61 * "warehouse", because in addition to generating the matchers, it also retains ownership of them. The
62 * warehouse must stay in scope for the whole lifespan of the AffixPatternMatcher that uses matchers from
63 * the warehouse.
64 *
65 * @author sffc
66 */
67// Exported as U_I18N_API_CLASS for tests
68class U_I18N_API_CLASS AffixTokenMatcherWarehouse : public UMemory {
69 public:
70 AffixTokenMatcherWarehouse() = default; // WARNING: Leaves the object in an unusable state
71
72 U_I18N_API AffixTokenMatcherWarehouse(const AffixTokenMatcherSetupData* setupData);
73
74 NumberParseMatcher& minusSign();
75
76 NumberParseMatcher& plusSign();
77
78 NumberParseMatcher& approximatelySign();
79
80 NumberParseMatcher& percent();
81
82 NumberParseMatcher& permille();
83
84 U_I18N_API NumberParseMatcher& currency(UErrorCode& status);
85
86 IgnorablesMatcher& ignorables();
87
88 NumberParseMatcher* nextCodePointMatcher(UChar32 cp, UErrorCode& status);
89
90 bool hasEmptyCurrencySymbol() const;
91
92 private:
93 // NOTE: The following field may be unsafe to access after construction is done!
94 const AffixTokenMatcherSetupData* fSetupData;
95
96 // NOTE: These are default-constructed and should not be used until initialized.
97 MinusSignMatcher fMinusSign;
98 PlusSignMatcher fPlusSign;
99 ApproximatelySignMatcher fApproximatelySign;
100 PercentMatcher fPercent;
101 PermilleMatcher fPermille;
102 CombinedCurrencyMatcher fCurrency;
103
104 // Use a child class for code point matchers, since it requires non-default operators.
105 MemoryPool<CodePointMatcher> fCodePoints;
106
107 friend class AffixPatternMatcherBuilder;
108 friend class AffixPatternMatcher;
109};
110
111
112class AffixPatternMatcherBuilder : public TokenConsumer, public MutableMatcherCollection {
113 public:
114 AffixPatternMatcherBuilder(const UnicodeString& pattern, AffixTokenMatcherWarehouse& warehouse,
115 IgnorablesMatcher* ignorables);
116
117 void consumeToken(::icu::number::impl::AffixPatternType type, UChar32 cp, UErrorCode& status) override;
118
119 /** NOTE: You can build only once! */
120 AffixPatternMatcher build(UErrorCode& status);
121
122 private:
123 ArraySeriesMatcher::MatcherArray fMatchers;
124 int32_t fMatchersLen;
125 int32_t fLastTypeOrCp;
126
127 const UnicodeString& fPattern;
128 AffixTokenMatcherWarehouse& fWarehouse;
129 IgnorablesMatcher* fIgnorables;
130
131 void addMatcher(NumberParseMatcher& matcher) override;
132};
133
134
135// Exported as U_I18N_API_CLASS for tests
136class U_I18N_API_CLASS AffixPatternMatcher : public ArraySeriesMatcher {
137 public:
138 AffixPatternMatcher() = default; // WARNING: Leaves the object in an unusable state
139
140 U_I18N_API static AffixPatternMatcher fromAffixPattern(const UnicodeString& affixPattern,
141 AffixTokenMatcherWarehouse& warehouse,
142 parse_flags_t parseFlags, bool* success,
143 UErrorCode& status);
144
145 UnicodeString getPattern() const;
146
147 bool operator==(const AffixPatternMatcher& other) const;
148
149 private:
150 CompactUnicodeString<4> fPattern;
151
152 AffixPatternMatcher(MatcherArray& matchers, int32_t matchersLen, const UnicodeString& pattern,
153 UErrorCode& status);
154
155 friend class AffixPatternMatcherBuilder;
156};
157
158
159class AffixMatcher : public NumberParseMatcher, public UMemory {
160 public:
161 AffixMatcher() = default; // WARNING: Leaves the object in an unusable state
162
163 AffixMatcher(AffixPatternMatcher* prefix, AffixPatternMatcher* suffix, result_flags_t flags);
164
165 bool match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const override;
166
167 void postProcess(ParsedNumber& result) const override;
168
169 bool smokeTest(const StringSegment& segment) const override;
170
171 int8_t compareTo(const AffixMatcher& rhs) const;
172
173 UnicodeString toString() const override;
174
175 private:
176 AffixPatternMatcher* fPrefix;
177 AffixPatternMatcher* fSuffix;
178 result_flags_t fFlags;
179};
180
181
182/**
183 * A C++-only class to retain ownership of the AffixMatchers needed for parsing.
184 */
185class AffixMatcherWarehouse {
186 public:
187 AffixMatcherWarehouse() = default; // WARNING: Leaves the object in an unusable state
188
189 AffixMatcherWarehouse(AffixTokenMatcherWarehouse* tokenWarehouse);
190
191 void createAffixMatchers(const AffixPatternProvider& patternInfo, MutableMatcherCollection& output,
192 const IgnorablesMatcher& ignorables, parse_flags_t parseFlags,
193 UErrorCode& status);
194
195 private:
196 // 18 is the limit: positive, zero, and negative, each with prefix, suffix, and prefix+suffix,
197 // and doubled since there may be an empty currency symbol
198 AffixMatcher fAffixMatchers[18];
199 // 6 is the limit: positive, zero, and negative, a prefix and a suffix for each,
200 // and doubled since there may be an empty currency symbol
201 AffixPatternMatcher fAffixPatternMatchers[12];
202 // Reference to the warehouse for tokens used by the AffixPatternMatchers
203 AffixTokenMatcherWarehouse* fTokenWarehouse;
204
205 friend class AffixMatcher;
206
207 static bool isInteresting(const AffixPatternProvider& patternInfo, const IgnorablesMatcher& ignorables,
208 parse_flags_t parseFlags, UErrorCode& status);
209};
210
211} // namespace numparse::impl
212
213U_NAMESPACE_END}
214
215#endif //__NUMPARSE_AFFIXES_H__
216#endif /* #if !UCONFIG_NO_FORMATTING */

/usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/bits/move.h

1// Move, forward and identity for C++11 + swap -*- C++ -*-
2
3// Copyright (C) 2007-2026 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/move.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{utility}
28 */
29
30#ifndef _MOVE_H1
31#define _MOVE_H1 1
32
33#include <bits/c++config.h>
34#if __cplusplus202002L < 201103L
35# include <bits/concept_check.h>
36#else
37# include <type_traits> // Brings in std::declval too.
38#endif
39
40namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
41{
42_GLIBCXX_BEGIN_NAMESPACE_VERSION
43
44 // Used, in C++03 mode too, by allocators, etc.
45 /**
46 * @brief Same as C++11 std::addressof
47 * @ingroup utilities
48 */
49 template<typename _Tp>
50 __attribute__((__always_inline__))
51 inline _GLIBCXX_CONSTEXPRconstexpr _Tp*
52 __addressof(_Tp& __r) _GLIBCXX_NOEXCEPTnoexcept
53 { return __builtin_addressof(__r); }
54
55#if __cplusplus202002L >= 201103L
56
57 /**
58 * @addtogroup utilities
59 * @{
60 */
61
62 /**
63 * @brief Forward an lvalue.
64 * @return The parameter cast to the specified type.
65 *
66 * This function is used to implement "perfect forwarding".
67 * @since C++11
68 */
69 template<typename _Tp>
70 [[__nodiscard__,__gnu__::__always_inline__]]
71 constexpr _Tp&&
72 forward(typename std::remove_reference<_Tp>::type& __t) noexcept
73 { return static_cast<_Tp&&>(__t); }
74
75 /**
76 * @brief Forward an rvalue.
77 * @return The parameter cast to the specified type.
78 *
79 * This function is used to implement "perfect forwarding".
80 * @since C++11
81 */
82 template<typename _Tp>
83 [[__nodiscard__,__gnu__::__always_inline__]]
84 constexpr _Tp&&
85 forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
86 {
87 static_assert(!std::is_lvalue_reference<_Tp>::value,
88 "std::forward must not be used to convert an rvalue to an lvalue");
89 return static_cast<_Tp&&>(__t);
90 }
91
92 template<typename _Tp, typename _Up>
93 struct __like_impl; // _Tp must be a reference and _Up an lvalue reference
94
95 template<typename _Tp, typename _Up>
96 struct __like_impl<_Tp&, _Up&>
97 { using type = _Up&; };
98
99 template<typename _Tp, typename _Up>
100 struct __like_impl<const _Tp&, _Up&>
101 { using type = const _Up&; };
102
103 template<typename _Tp, typename _Up>
104 struct __like_impl<_Tp&&, _Up&>
105 { using type = _Up&&; };
106
107 template<typename _Tp, typename _Up>
108 struct __like_impl<const _Tp&&, _Up&>
109 { using type = const _Up&&; };
110
111 template<typename _Tp, typename _Up>
112 using __like_t = typename __like_impl<_Tp&&, _Up&>::type;
113
114#if __glibcxx_forward_like // C++ >= 23
115 /** @brief Forward with the cv-qualifiers and value category of another type.
116 * @tparam _Tp An lvalue reference or rvalue reference.
117 * @tparam _Up An lvalue reference type deduced from the function argument.
118 * @param __x An lvalue.
119 * @return `__x` converted to match the qualifiers of `_Tp`.
120 * @since C++23
121 */
122 template<typename _Tp, typename _Up>
123 [[nodiscard,__gnu__::__always_inline__]]
124 constexpr __like_t<_Tp, _Up>
125 forward_like(_Up&& __x) noexcept
126 { return static_cast<__like_t<_Tp, _Up>>(__x); }
127#endif
128
129 /**
130 * @brief Convert a value to an rvalue.
131 * @param __t A thing of arbitrary type.
132 * @return The parameter cast to an rvalue-reference to allow moving it.
133 * @since C++11
134 */
135 template<typename _Tp>
136 [[__nodiscard__,__gnu__::__always_inline__]]
137 constexpr typename std::remove_reference<_Tp>::type&&
138 move(_Tp&& __t) noexcept
139 { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
140
141
142 template<typename _Tp>
143 struct __move_if_noexcept_cond
144 : public __and_<__not_<is_nothrow_move_constructible<_Tp>>,
145 is_copy_constructible<_Tp>>::type { };
146
147 /**
148 * @brief Conditionally convert a value to an rvalue.
149 * @param __x A thing of arbitrary type.
150 * @return The parameter, possibly cast to an rvalue-reference.
151 *
152 * Same as std::move unless the type's move constructor could throw and the
153 * type is copyable, in which case an lvalue-reference is returned instead.
154 * @since C++11
155 */
156 template<typename _Tp>
157 [[__nodiscard__,__gnu__::__always_inline__]]
158 constexpr
159 __conditional_t<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>
160 move_if_noexcept(_Tp& __x) noexcept
161 { return std::move(__x); }
162
163 // declval, from type_traits.
164
165 /**
166 * @brief Returns the actual address of the object or function
167 * referenced by r, even in the presence of an overloaded
168 * operator&.
169 * @param __r Reference to an object or function.
170 * @return The actual address.
171 * @since C++11
172 */
173 template<typename _Tp>
174 [[__nodiscard__,__gnu__::__always_inline__]]
175 inline _GLIBCXX17_CONSTEXPRconstexpr _Tp*
176 addressof(_Tp& __r) noexcept
177 { return __builtin_addressof(__r); }
178
179 // _GLIBCXX_RESOLVE_LIB_DEFECTS
180 // 2598. addressof works on temporaries
181 template<typename _Tp>
182 const _Tp* addressof(const _Tp&&) = delete;
183
184 // C++11 version of std::exchange for internal use.
185 template <typename _Tp, typename _Up = _Tp>
186 _GLIBCXX20_CONSTEXPRconstexpr
187 inline _Tp
188 __exchange(_Tp& __obj, _Up&& __new_val)
189 {
190 _Tp __old_val = std::move(__obj);
191 __obj = std::forward<_Up>(__new_val);
192 return __old_val;
193 }
194
195 /// @} group utilities
196
197#define _GLIBCXX_FWDREF(_Tp)_Tp&& _Tp&&
198#define _GLIBCXX_MOVE(__val)std::move(__val) std::move(__val)
199#define _GLIBCXX_FORWARD(_Tp, __val)std::forward<_Tp>(__val) std::forward<_Tp>(__val)
200#else
201#define _GLIBCXX_FWDREF(_Tp)_Tp&& const _Tp&
202#define _GLIBCXX_MOVE(__val)std::move(__val) (__val)
203#define _GLIBCXX_FORWARD(_Tp, __val)std::forward<_Tp>(__val) (__val)
204#endif
205
206 /**
207 * @addtogroup utilities
208 * @{
209 */
210
211 /**
212 * @brief Swaps two values.
213 * @param __a A thing of arbitrary type.
214 * @param __b Another thing of arbitrary type.
215 */
216 template<typename _Tp>
217#if __glibcxx_concepts202207L // >= C++20
218 requires (! __is_tuple_like<_Tp>::value)
219 && is_move_constructible_v<_Tp>
220 && is_move_assignable_v<_Tp>
221 constexpr void
222#elif __cplusplus202002L >= 201103L
223 _GLIBCXX20_CONSTEXPRconstexpr inline
224 __enable_if_t<__and_<__not_<__is_tuple_like<_Tp>>,
225 is_move_constructible<_Tp>,
226 is_move_assignable<_Tp>>::value>
227#else
228 inline void
229#endif
230 swap(_Tp& __a, _Tp& __b)
231 _GLIBCXX_NOEXCEPT_IF(__and_<is_nothrow_move_constructible<_Tp>,noexcept(__and_<is_nothrow_move_constructible<_Tp>, is_nothrow_move_assignable
<_Tp>>::value)
232 is_nothrow_move_assignable<_Tp>>::value)noexcept(__and_<is_nothrow_move_constructible<_Tp>, is_nothrow_move_assignable
<_Tp>>::value)
233 {
234#if __cplusplus202002L < 201103L
235 // concept requirements
236 __glibcxx_function_requires(_SGIAssignableConcept<_Tp>)
237#endif
238 _Tp __tmp = _GLIBCXX_MOVE(__a)std::move(__a);
239 __a = _GLIBCXX_MOVE(__b)std::move(__b);
240 __b = _GLIBCXX_MOVE(__tmp)std::move(__tmp);
19
Calling move assignment operator for 'MaybeStackArray<icu_78::numparse::impl::CodePointMatcher *, 8>'
241 }
242
243 // _GLIBCXX_RESOLVE_LIB_DEFECTS
244 // DR 809. std::swap should be overloaded for array types.
245 /// Swap the contents of two arrays.
246 template<typename _Tp, size_t _Nm>
247#if __glibcxx_concepts202207L // >= C++20
248 requires is_swappable_v<_Tp>
249 constexpr void
250#elif __cplusplus202002L >= 201103L
251 _GLIBCXX20_CONSTEXPRconstexpr inline
252 __enable_if_t<__is_swappable<_Tp>::value>
253#else
254 inline void
255#endif
256 swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
257 _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Tp>::value)noexcept(__is_nothrow_swappable<_Tp>::value)
258 {
259 for (size_t __n = 0; __n < _Nm; ++__n)
260 swap(__a[__n], __b[__n]);
261 }
262
263 /// @} group utilities
264_GLIBCXX_END_NAMESPACE_VERSION
265} // namespace
266
267#endif /* _MOVE_H */