#include <stdio.h>
#endif
-#if U_DEBUG
-
-/*
- * The C++ standard requires that the source pointer for memcpy() & memmove()
- * is valid, not NULL, and not at the end of an allocated memory block.
- * In debug mode, we read one byte from the source point to verify that it's
- * a valid, readable pointer.
- */
-
-U_CAPI void uprv_checkValidMemory(const void *p, size_t n);
-
-#define uprv_memcpy(dst, src, size) ( \
- uprv_checkValidMemory(src, 1), \
- U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size))
-#define uprv_memmove(dst, src, size) ( \
- uprv_checkValidMemory(src, 1), \
- U_STANDARD_CPP_NAMESPACE memmove(dst, src, size))
-
-#else
#define uprv_memcpy(dst, src, size) U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size)
#define uprv_memmove(dst, src, size) U_STANDARD_CPP_NAMESPACE memmove(dst, src, size)
-#endif /* U_DEBUG */
-
/**
* \def UPRV_LENGTHOF
* Convenience macro to determine the length of a fixed array at compile-time.
* @param p simple pointer to an array of T items that is adopted
*/
explicit LocalMemory(T *p=NULL) : LocalPointerBase<T>(p) {}
-#if U_HAVE_RVALUE_REFERENCES
/**
* Move constructor, leaves src with isNull().
* @param src source smart pointer
LocalMemory(LocalMemory<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
src.ptr=NULL;
}
-#endif
/**
* Destructor deletes the memory it owns.
*/
~LocalMemory() {
uprv_free(LocalPointerBase<T>::ptr);
}
-#if U_HAVE_RVALUE_REFERENCES
/**
* Move assignment operator, leaves src with isNull().
* The behavior is undefined if *this and src are the same object.
LocalMemory<T> &operator=(LocalMemory<T> &&src) U_NOEXCEPT {
return moveFrom(src);
}
-#endif
/**
* Move assignment, leaves src with isNull().
* The behavior is undefined if *this and src are the same object.
* Default constructor initializes with internal T[stackCapacity] buffer.
*/
MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(FALSE) {}
+ /**
+ * Automatically allocates the heap array if the argument is larger than the stack capacity.
+ * Intended for use when an approximate capacity is known at compile time but the true
+ * capacity is not known until runtime.
+ */
+ MaybeStackArray(int32_t newCapacity) : MaybeStackArray() {
+ if (capacity < newCapacity) { resize(newCapacity); }
+ };
/**
* Destructor deletes the array (if owned).
*/
~MaybeStackArray() { releaseArray(); }
+ /**
+ * Move constructor: transfers ownership or copies the stack array.
+ */
+ MaybeStackArray(MaybeStackArray<T, stackCapacity> &&src) U_NOEXCEPT;
+ /**
+ * Move assignment: transfers ownership or copies the stack array.
+ */
+ MaybeStackArray<T, stackCapacity> &operator=(MaybeStackArray<T, stackCapacity> &&src) U_NOEXCEPT;
/**
* Returns the array capacity (number of T items).
* @return array capacity
uprv_free(ptr);
}
}
+ void resetToStackArray() {
+ ptr=stackArray;
+ capacity=stackCapacity;
+ needToRelease=FALSE;
+ }
/* No comparison operators with other MaybeStackArray's. */
bool operator==(const MaybeStackArray & /*other*/) {return FALSE;}
bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;}
#endif
};
+template<typename T, int32_t stackCapacity>
+icu::MaybeStackArray<T, stackCapacity>::MaybeStackArray(
+ MaybeStackArray <T, stackCapacity>&& src) U_NOEXCEPT
+ : ptr(src.ptr), capacity(src.capacity), needToRelease(src.needToRelease) {
+ if (src.ptr == src.stackArray) {
+ ptr = stackArray;
+ uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity);
+ } else {
+ src.resetToStackArray(); // take ownership away from src
+ }
+}
+
+template<typename T, int32_t stackCapacity>
+inline MaybeStackArray <T, stackCapacity>&
+MaybeStackArray<T, stackCapacity>::operator=(MaybeStackArray <T, stackCapacity>&& src) U_NOEXCEPT {
+ releaseArray(); // in case this instance had its own memory allocated
+ capacity = src.capacity;
+ needToRelease = src.needToRelease;
+ if (src.ptr == src.stackArray) {
+ ptr = stackArray;
+ uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity);
+ } else {
+ ptr = src.ptr;
+ src.resetToStackArray(); // take ownership away from src
+ }
+ return *this;
+}
+
template<typename T, int32_t stackCapacity>
inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) {
if(newCapacity>0) {
uprv_memcpy(p, ptr, (size_t)length*sizeof(T));
}
resultCapacity=length;
- ptr=stackArray;
- capacity=stackCapacity;
- needToRelease=FALSE;
+ resetToStackArray();
return p;
}