]> git.saurik.com Git - apple/icu.git/blame_incremental - icuSources/common/cmemory.h
ICU-57149.0.1.tar.gz
[apple/icu.git] / icuSources / common / cmemory.h
... / ...
CommitLineData
1/*
2******************************************************************************
3*
4* Copyright (C) 1997-2016, International Business Machines
5* Corporation and others. All Rights Reserved.
6*
7******************************************************************************
8*
9* File CMEMORY.H
10*
11* Contains stdlib.h/string.h memory functions
12*
13* @author Bertrand A. Damiba
14*
15* Modification History:
16*
17* Date Name Description
18* 6/20/98 Bertrand Created.
19* 05/03/99 stephen Changed from functions to macros.
20*
21******************************************************************************
22*/
23
24#ifndef CMEMORY_H
25#define CMEMORY_H
26
27#include "unicode/utypes.h"
28
29#include <stddef.h>
30#include <string.h>
31#include "unicode/localpointer.h"
32
33#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
34#include <stdio.h>
35#endif
36
37#if U_DEBUG
38
39/*
40 * The C++ standard requires that the source pointer for memcpy() & memmove()
41 * is valid, not NULL, and not at the end of an allocated memory block.
42 * In debug mode, we read one byte from the source point to verify that it's
43 * a valid, readable pointer.
44 */
45
46U_CAPI void uprv_checkValidMemory(const void *p, size_t n);
47
48#define uprv_memcpy(dst, src, size) ( \
49 uprv_checkValidMemory(src, 1), \
50 U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size))
51#define uprv_memmove(dst, src, size) ( \
52 uprv_checkValidMemory(src, 1), \
53 U_STANDARD_CPP_NAMESPACE memmove(dst, src, size))
54
55#else
56
57#define uprv_memcpy(dst, src, size) U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size)
58#define uprv_memmove(dst, src, size) U_STANDARD_CPP_NAMESPACE memmove(dst, src, size)
59
60#endif /* U_DEBUG */
61
62/**
63 * \def UPRV_LENGTHOF
64 * Convenience macro to determine the length of a fixed array at compile-time.
65 * @param array A fixed length array
66 * @return The length of the array, in elements
67 * @internal
68 */
69#define UPRV_LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
70#define uprv_memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE memset(buffer, mark, size)
71#define uprv_memcmp(buffer1, buffer2, size) U_STANDARD_CPP_NAMESPACE memcmp(buffer1, buffer2,size)
72
73U_CAPI void * U_EXPORT2
74uprv_malloc(size_t s) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR(1);
75
76U_CAPI void * U_EXPORT2
77uprv_realloc(void *mem, size_t size) U_ALLOC_SIZE_ATTR(2);
78
79U_CAPI void U_EXPORT2
80uprv_free(void *mem);
81
82U_CAPI void * U_EXPORT2
83uprv_calloc(size_t num, size_t size) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR2(1,2);
84
85/**
86 * This should align the memory properly on any machine.
87 * This is very useful for the safeClone functions.
88 */
89typedef union {
90 long t1;
91 double t2;
92 void *t3;
93} UAlignedMemory;
94
95/**
96 * Get the least significant bits of a pointer (a memory address).
97 * For example, with a mask of 3, the macro gets the 2 least significant bits,
98 * which will be 0 if the pointer is 32-bit (4-byte) aligned.
99 *
100 * ptrdiff_t is the most appropriate integer type to cast to.
101 * size_t should work too, since on most (or all?) platforms it has the same
102 * width as ptrdiff_t.
103 */
104#define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask))
105
106/**
107 * Get the amount of bytes that a pointer is off by from
108 * the previous UAlignedMemory-aligned pointer.
109 */
110#define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1)
111
112/**
113 * Get the amount of bytes to add to a pointer
114 * in order to get the next UAlignedMemory-aligned address.
115 */
116#define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr))
117
118/**
119 * Heap clean up function, called from u_cleanup()
120 * Clears any user heap functions from u_setMemoryFunctions()
121 * Does NOT deallocate any remaining allocated memory.
122 */
123U_CFUNC UBool
124cmemory_cleanup(void);
125
126/**
127 * A function called by <TT>uhash_remove</TT>,
128 * <TT>uhash_close</TT>, or <TT>uhash_put</TT> to delete
129 * an existing key or value.
130 * @param obj A key or value stored in a hashtable
131 * @see uprv_deleteUObject
132 */
133typedef void U_CALLCONV UObjectDeleter(void* obj);
134
135/**
136 * Deleter for UObject instances.
137 * Works for all subclasses of UObject because it has a virtual destructor.
138 */
139U_CAPI void U_EXPORT2
140uprv_deleteUObject(void *obj);
141
142#ifdef __cplusplus
143
144U_NAMESPACE_BEGIN
145
146/**
147 * "Smart pointer" class, deletes memory via uprv_free().
148 * For most methods see the LocalPointerBase base class.
149 * Adds operator[] for array item access.
150 *
151 * @see LocalPointerBase
152 */
153template<typename T>
154class LocalMemory : public LocalPointerBase<T> {
155public:
156 using LocalPointerBase<T>::operator*;
157 using LocalPointerBase<T>::operator->;
158 /**
159 * Constructor takes ownership.
160 * @param p simple pointer to an array of T items that is adopted
161 */
162 explicit LocalMemory(T *p=NULL) : LocalPointerBase<T>(p) {}
163#if U_HAVE_RVALUE_REFERENCES
164 /**
165 * Move constructor, leaves src with isNull().
166 * @param src source smart pointer
167 */
168 LocalMemory(LocalMemory<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
169 src.ptr=NULL;
170 }
171#endif
172 /**
173 * Destructor deletes the memory it owns.
174 */
175 ~LocalMemory() {
176 uprv_free(LocalPointerBase<T>::ptr);
177 }
178#if U_HAVE_RVALUE_REFERENCES
179 /**
180 * Move assignment operator, leaves src with isNull().
181 * The behavior is undefined if *this and src are the same object.
182 * @param src source smart pointer
183 * @return *this
184 */
185 LocalMemory<T> &operator=(LocalMemory<T> &&src) U_NOEXCEPT {
186 return moveFrom(src);
187 }
188#endif
189 /**
190 * Move assignment, leaves src with isNull().
191 * The behavior is undefined if *this and src are the same object.
192 *
193 * Can be called explicitly, does not need C++11 support.
194 * @param src source smart pointer
195 * @return *this
196 */
197 LocalMemory<T> &moveFrom(LocalMemory<T> &src) U_NOEXCEPT {
198 delete[] LocalPointerBase<T>::ptr;
199 LocalPointerBase<T>::ptr=src.ptr;
200 src.ptr=NULL;
201 return *this;
202 }
203 /**
204 * Swap pointers.
205 * @param other other smart pointer
206 */
207 void swap(LocalMemory<T> &other) U_NOEXCEPT {
208 T *temp=LocalPointerBase<T>::ptr;
209 LocalPointerBase<T>::ptr=other.ptr;
210 other.ptr=temp;
211 }
212 /**
213 * Non-member LocalMemory swap function.
214 * @param p1 will get p2's pointer
215 * @param p2 will get p1's pointer
216 */
217 friend inline void swap(LocalMemory<T> &p1, LocalMemory<T> &p2) U_NOEXCEPT {
218 p1.swap(p2);
219 }
220 /**
221 * Deletes the array it owns,
222 * and adopts (takes ownership of) the one passed in.
223 * @param p simple pointer to an array of T items that is adopted
224 */
225 void adoptInstead(T *p) {
226 uprv_free(LocalPointerBase<T>::ptr);
227 LocalPointerBase<T>::ptr=p;
228 }
229 /**
230 * Deletes the array it owns, allocates a new one and reset its bytes to 0.
231 * Returns the new array pointer.
232 * If the allocation fails, then the current array is unchanged and
233 * this method returns NULL.
234 * @param newCapacity must be >0
235 * @return the allocated array pointer, or NULL if the allocation failed
236 */
237 inline T *allocateInsteadAndReset(int32_t newCapacity=1);
238 /**
239 * Deletes the array it owns and allocates a new one, copying length T items.
240 * Returns the new array pointer.
241 * If the allocation fails, then the current array is unchanged and
242 * this method returns NULL.
243 * @param newCapacity must be >0
244 * @param length number of T items to be copied from the old array to the new one;
245 * must be no more than the capacity of the old array,
246 * which the caller must track because the LocalMemory does not track it
247 * @return the allocated array pointer, or NULL if the allocation failed
248 */
249 inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0);
250 /**
251 * Array item access (writable).
252 * No index bounds check.
253 * @param i array index
254 * @return reference to the array item
255 */
256 T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
257};
258
259template<typename T>
260inline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) {
261 if(newCapacity>0) {
262 T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
263 if(p!=NULL) {
264 uprv_memset(p, 0, newCapacity*sizeof(T));
265 uprv_free(LocalPointerBase<T>::ptr);
266 LocalPointerBase<T>::ptr=p;
267 }
268 return p;
269 } else {
270 return NULL;
271 }
272}
273
274
275template<typename T>
276inline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) {
277 if(newCapacity>0) {
278 T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
279 if(p!=NULL) {
280 if(length>0) {
281 if(length>newCapacity) {
282 length=newCapacity;
283 }
284 uprv_memcpy(p, LocalPointerBase<T>::ptr, (size_t)length*sizeof(T));
285 }
286 uprv_free(LocalPointerBase<T>::ptr);
287 LocalPointerBase<T>::ptr=p;
288 }
289 return p;
290 } else {
291 return NULL;
292 }
293}
294
295/**
296 * Simple array/buffer management class using uprv_malloc() and uprv_free().
297 * Provides an internal array with fixed capacity. Can alias another array
298 * or allocate one.
299 *
300 * The array address is properly aligned for type T. It might not be properly
301 * aligned for types larger than T (or larger than the largest subtype of T).
302 *
303 * Unlike LocalMemory and LocalArray, this class never adopts
304 * (takes ownership of) another array.
305 */
306template<typename T, int32_t stackCapacity>
307class MaybeStackArray {
308public:
309 /**
310 * Default constructor initializes with internal T[stackCapacity] buffer.
311 */
312 MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(FALSE) {}
313 /**
314 * Destructor deletes the array (if owned).
315 */
316 ~MaybeStackArray() { releaseArray(); }
317 /**
318 * Returns the array capacity (number of T items).
319 * @return array capacity
320 */
321 int32_t getCapacity() const { return capacity; }
322 /**
323 * Access without ownership change.
324 * @return the array pointer
325 */
326 T *getAlias() const { return ptr; }
327 /**
328 * Returns the array limit. Simple convenience method.
329 * @return getAlias()+getCapacity()
330 */
331 T *getArrayLimit() const { return getAlias()+capacity; }
332 // No "operator T *() const" because that can make
333 // expressions like mbs[index] ambiguous for some compilers.
334 /**
335 * Array item access (const).
336 * No index bounds check.
337 * @param i array index
338 * @return reference to the array item
339 */
340 const T &operator[](ptrdiff_t i) const { return ptr[i]; }
341 /**
342 * Array item access (writable).
343 * No index bounds check.
344 * @param i array index
345 * @return reference to the array item
346 */
347 T &operator[](ptrdiff_t i) { return ptr[i]; }
348 /**
349 * Deletes the array (if owned) and aliases another one, no transfer of ownership.
350 * If the arguments are illegal, then the current array is unchanged.
351 * @param otherArray must not be NULL
352 * @param otherCapacity must be >0
353 */
354 void aliasInstead(T *otherArray, int32_t otherCapacity) {
355 if(otherArray!=NULL && otherCapacity>0) {
356 releaseArray();
357 ptr=otherArray;
358 capacity=otherCapacity;
359 needToRelease=FALSE;
360 }
361 }
362 /**
363 * Deletes the array (if owned) and allocates a new one, copying length T items.
364 * Returns the new array pointer.
365 * If the allocation fails, then the current array is unchanged and
366 * this method returns NULL.
367 * @param newCapacity can be less than or greater than the current capacity;
368 * must be >0
369 * @param length number of T items to be copied from the old array to the new one
370 * @return the allocated array pointer, or NULL if the allocation failed
371 */
372 inline T *resize(int32_t newCapacity, int32_t length=0);
373 /**
374 * Gives up ownership of the array if owned, or else clones it,
375 * copying length T items; resets itself to the internal stack array.
376 * Returns NULL if the allocation failed.
377 * @param length number of T items to copy when cloning,
378 * and capacity of the clone when cloning
379 * @param resultCapacity will be set to the returned array's capacity (output-only)
380 * @return the array pointer;
381 * caller becomes responsible for deleting the array
382 */
383 inline T *orphanOrClone(int32_t length, int32_t &resultCapacity);
384private:
385 T *ptr;
386 int32_t capacity;
387 UBool needToRelease;
388 T stackArray[stackCapacity];
389 void releaseArray() {
390 if(needToRelease) {
391 uprv_free(ptr);
392 }
393 }
394 /* No comparison operators with other MaybeStackArray's. */
395 bool operator==(const MaybeStackArray & /*other*/) {return FALSE;}
396 bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;}
397 /* No ownership transfer: No copy constructor, no assignment operator. */
398 MaybeStackArray(const MaybeStackArray & /*other*/) {}
399 void operator=(const MaybeStackArray & /*other*/) {}
400
401 // No heap allocation. Use only on the stack.
402 // (Declaring these functions private triggers a cascade of problems:
403 // MSVC insists on exporting an instantiation of MaybeStackArray, which
404 // requires that all functions be defined.
405 // An empty implementation of new() is rejected, it must return a value.
406 // Returning NULL is rejected by gcc for operator new.
407 // The expedient thing is just not to override operator new.
408 // While relatively pointless, heap allocated instances will function.
409 // static void * U_EXPORT2 operator new(size_t size);
410 // static void * U_EXPORT2 operator new[](size_t size);
411#if U_HAVE_PLACEMENT_NEW
412 // static void * U_EXPORT2 operator new(size_t, void *ptr);
413#endif
414};
415
416template<typename T, int32_t stackCapacity>
417inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) {
418 if(newCapacity>0) {
419#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
420 ::fprintf(::stderr,"MaybeStacArray (resize) alloc %d * %lu\n", newCapacity,sizeof(T));
421#endif
422 T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
423 if(p!=NULL) {
424 if(length>0) {
425 if(length>capacity) {
426 length=capacity;
427 }
428 if(length>newCapacity) {
429 length=newCapacity;
430 }
431 uprv_memcpy(p, ptr, (size_t)length*sizeof(T));
432 }
433 releaseArray();
434 ptr=p;
435 capacity=newCapacity;
436 needToRelease=TRUE;
437 }
438 return p;
439 } else {
440 return NULL;
441 }
442}
443
444template<typename T, int32_t stackCapacity>
445inline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) {
446 T *p;
447 if(needToRelease) {
448 p=ptr;
449 } else if(length<=0) {
450 return NULL;
451 } else {
452 if(length>capacity) {
453 length=capacity;
454 }
455 p=(T *)uprv_malloc(length*sizeof(T));
456#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
457 ::fprintf(::stderr,"MaybeStacArray (orphan) alloc %d * %lu\n", length,sizeof(T));
458#endif
459 if(p==NULL) {
460 return NULL;
461 }
462 uprv_memcpy(p, ptr, (size_t)length*sizeof(T));
463 }
464 resultCapacity=length;
465 ptr=stackArray;
466 capacity=stackCapacity;
467 needToRelease=FALSE;
468 return p;
469}
470
471/**
472 * Variant of MaybeStackArray that allocates a header struct and an array
473 * in one contiguous memory block, using uprv_malloc() and uprv_free().
474 * Provides internal memory with fixed array capacity. Can alias another memory
475 * block or allocate one.
476 * The stackCapacity is the number of T items in the internal memory,
477 * not counting the H header.
478 * Unlike LocalMemory and LocalArray, this class never adopts
479 * (takes ownership of) another memory block.
480 */
481template<typename H, typename T, int32_t stackCapacity>
482class MaybeStackHeaderAndArray {
483public:
484 /**
485 * Default constructor initializes with internal H+T[stackCapacity] buffer.
486 */
487 MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(FALSE) {}
488 /**
489 * Destructor deletes the memory (if owned).
490 */
491 ~MaybeStackHeaderAndArray() { releaseMemory(); }
492 /**
493 * Returns the array capacity (number of T items).
494 * @return array capacity
495 */
496 int32_t getCapacity() const { return capacity; }
497 /**
498 * Access without ownership change.
499 * @return the header pointer
500 */
501 H *getAlias() const { return ptr; }
502 /**
503 * Returns the array start.
504 * @return array start, same address as getAlias()+1
505 */
506 T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); }
507 /**
508 * Returns the array limit.
509 * @return array limit
510 */
511 T *getArrayLimit() const { return getArrayStart()+capacity; }
512 /**
513 * Access without ownership change. Same as getAlias().
514 * A class instance can be used directly in expressions that take a T *.
515 * @return the header pointer
516 */
517 operator H *() const { return ptr; }
518 /**
519 * Array item access (writable).
520 * No index bounds check.
521 * @param i array index
522 * @return reference to the array item
523 */
524 T &operator[](ptrdiff_t i) { return getArrayStart()[i]; }
525 /**
526 * Deletes the memory block (if owned) and aliases another one, no transfer of ownership.
527 * If the arguments are illegal, then the current memory is unchanged.
528 * @param otherArray must not be NULL
529 * @param otherCapacity must be >0
530 */
531 void aliasInstead(H *otherMemory, int32_t otherCapacity) {
532 if(otherMemory!=NULL && otherCapacity>0) {
533 releaseMemory();
534 ptr=otherMemory;
535 capacity=otherCapacity;
536 needToRelease=FALSE;
537 }
538 }
539 /**
540 * Deletes the memory block (if owned) and allocates a new one,
541 * copying the header and length T array items.
542 * Returns the new header pointer.
543 * If the allocation fails, then the current memory is unchanged and
544 * this method returns NULL.
545 * @param newCapacity can be less than or greater than the current capacity;
546 * must be >0
547 * @param length number of T items to be copied from the old array to the new one
548 * @return the allocated pointer, or NULL if the allocation failed
549 */
550 inline H *resize(int32_t newCapacity, int32_t length=0);
551 /**
552 * Gives up ownership of the memory if owned, or else clones it,
553 * copying the header and length T array items; resets itself to the internal memory.
554 * Returns NULL if the allocation failed.
555 * @param length number of T items to copy when cloning,
556 * and array capacity of the clone when cloning
557 * @param resultCapacity will be set to the returned array's capacity (output-only)
558 * @return the header pointer;
559 * caller becomes responsible for deleting the array
560 */
561 inline H *orphanOrClone(int32_t length, int32_t &resultCapacity);
562private:
563 H *ptr;
564 int32_t capacity;
565 UBool needToRelease;
566 // stackHeader must precede stackArray immediately.
567 H stackHeader;
568 T stackArray[stackCapacity];
569 void releaseMemory() {
570 if(needToRelease) {
571 uprv_free(ptr);
572 }
573 }
574 /* No comparison operators with other MaybeStackHeaderAndArray's. */
575 bool operator==(const MaybeStackHeaderAndArray & /*other*/) {return FALSE;}
576 bool operator!=(const MaybeStackHeaderAndArray & /*other*/) {return TRUE;}
577 /* No ownership transfer: No copy constructor, no assignment operator. */
578 MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray & /*other*/) {}
579 void operator=(const MaybeStackHeaderAndArray & /*other*/) {}
580
581 // No heap allocation. Use only on the stack.
582 // (Declaring these functions private triggers a cascade of problems;
583 // see the MaybeStackArray class for details.)
584 // static void * U_EXPORT2 operator new(size_t size);
585 // static void * U_EXPORT2 operator new[](size_t size);
586#if U_HAVE_PLACEMENT_NEW
587 // static void * U_EXPORT2 operator new(size_t, void *ptr);
588#endif
589};
590
591template<typename H, typename T, int32_t stackCapacity>
592inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity,
593 int32_t length) {
594 if(newCapacity>=0) {
595#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
596 ::fprintf(::stderr,"MaybeStackHeaderAndArray alloc %d + %d * %ul\n", sizeof(H),newCapacity,sizeof(T));
597#endif
598 H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T));
599 if(p!=NULL) {
600 if(length<0) {
601 length=0;
602 } else if(length>0) {
603 if(length>capacity) {
604 length=capacity;
605 }
606 if(length>newCapacity) {
607 length=newCapacity;
608 }
609 }
610 uprv_memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof(T));
611 releaseMemory();
612 ptr=p;
613 capacity=newCapacity;
614 needToRelease=TRUE;
615 }
616 return p;
617 } else {
618 return NULL;
619 }
620}
621
622template<typename H, typename T, int32_t stackCapacity>
623inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length,
624 int32_t &resultCapacity) {
625 H *p;
626 if(needToRelease) {
627 p=ptr;
628 } else {
629 if(length<0) {
630 length=0;
631 } else if(length>capacity) {
632 length=capacity;
633 }
634#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
635 ::fprintf(::stderr,"MaybeStackHeaderAndArray (orphan) alloc %ul + %d * %lu\n", sizeof(H),length,sizeof(T));
636#endif
637 p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T));
638 if(p==NULL) {
639 return NULL;
640 }
641 uprv_memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof(T));
642 }
643 resultCapacity=length;
644 ptr=&stackHeader;
645 capacity=stackCapacity;
646 needToRelease=FALSE;
647 return p;
648}
649
650U_NAMESPACE_END
651
652#endif /* __cplusplus */
653#endif /* CMEMORY_H */