#if !UCONFIG_NO_CONVERSION
+#include <memory>
+
#include "unicode/ustring.h"
#include "unicode/ucnv.h"
#include "unicode/ucnv_err.h"
UConverter *localConverter, *allocatedConverter;
int32_t stackBufferSize;
int32_t bufferSizeNeeded;
- char *stackBufferChars = (char *)stackBuffer;
UErrorCode cbErr;
UConverterToUnicodeArgs toUArgs = {
sizeof(UConverterToUnicodeArgs),
}
}
-
- /* Pointers on 64-bit platforms need to be aligned
- * on a 64-bit boundary in memory.
+ /* Adjust (if necessary) the stackBuffer pointer to be aligned correctly for a UConverter.
+ * TODO(Jira ICU-20736) Redo this using std::align() once g++4.9 compatibility is no longer needed.
*/
- if (U_ALIGNMENT_OFFSET(stackBuffer) != 0) {
- int32_t offsetUp = (int32_t)U_ALIGNMENT_OFFSET_UP(stackBufferChars);
- if(stackBufferSize > offsetUp) {
- stackBufferSize -= offsetUp;
- stackBufferChars += offsetUp;
+ if (stackBuffer) {
+ uintptr_t p = reinterpret_cast<uintptr_t>(stackBuffer);
+ uintptr_t aligned_p = (p + alignof(UConverter) - 1) & ~(alignof(UConverter) - 1);
+ ptrdiff_t pointerAdjustment = aligned_p - p;
+ if (bufferSizeNeeded + pointerAdjustment <= stackBufferSize) {
+ stackBuffer = reinterpret_cast<void *>(aligned_p);
+ stackBufferSize -= static_cast<int32_t>(pointerAdjustment);
} else {
/* prevent using the stack buffer but keep the size > 0 so that we do not just preflight */
stackBufferSize = 1;
}
}
- stackBuffer = (void *)stackBufferChars;
-
/* Now, see if we must allocate any memory */
if (stackBufferSize < bufferSizeNeeded || stackBuffer == NULL)
{
const UChar *s,
int32_t length,
UErrorCode *err) {
- UAlignedMemory cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE / sizeof(UAlignedMemory) + 1];
+ alignas(UConverter) char cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE];
char chars[UCNV_ERROR_BUFFER_LENGTH];
UConverter *clone;