ICU-12992 return pointer-wrapper class from UnicodeString::getBuffer() and siblings, add wrapper class overloads to make this mostly work as is, fix a few call sites

X-SVN-Rev: 39715
This commit is contained in:
Markus Scherer 2017-02-28 22:07:03 +00:00
parent 9634351bd7
commit d924dda84b
8 changed files with 194 additions and 50 deletions

View File

@ -1030,7 +1030,8 @@ collectCurrencyNames(const char* locale,
const UnicodeString *symbol;
while ((symbol = iter.next()) != NULL) {
(*currencySymbols)[*total_currency_symbol_count].IsoCode = iso;
(*currencySymbols)[*total_currency_symbol_count].currencyName = (UChar*) symbol->getBuffer();
(*currencySymbols)[*total_currency_symbol_count].currencyName =
const_cast<UChar*>(symbol->getBuffer().get());
(*currencySymbols)[*total_currency_symbol_count].flag = 0;
(*currencySymbols)[(*total_currency_symbol_count)++].currencyNameLen = symbol->length();
}

View File

@ -79,6 +79,7 @@ class U_COMMON_API Char16Ptr final {
public:
/**
* Copies the pointer.
* TODO: @param p ...
* @draft ICU 59
*/
inline Char16Ptr(char16_t *p);
@ -107,21 +108,70 @@ public:
*/
Char16Ptr(int null);
/**
* Pointer access.
* Destructor.
* @draft ICU 59
*/
inline char16_t *get();
inline ~Char16Ptr();
/**
* Pointer access via type conversion (e.g., static_cast).
* Pointer access.
* TODO @return ...
* @draft ICU 59
*/
operator char16_t *() { return get(); }
inline char16_t *get() const;
/**
* char16_t pointer access via type conversion (e.g., static_cast).
* @draft ICU 59
*/
operator char16_t *() const { return get(); }
/**
* uint16_t pointer access via type conversion (e.g., static_cast).
* @draft ICU 59
*/
inline operator uint16_t *() const;
#if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
/**
* wchar_t pointer access via type conversion (e.g., static_cast).
* @draft ICU 59
*/
inline operator wchar_t *() const;
#endif
operator void *() const { return get(); }
char16_t operator[](size_t offset) const { return get()[offset]; }
UBool operator==(const Char16Ptr &other) const { return get() == other.get(); }
UBool operator!=(const Char16Ptr &other) const { return !operator==(other); }
UBool operator==(const char16_t *other) const { return get() == other; }
UBool operator!=(const char16_t *other) const { return !operator==(other); }
UBool operator==(const uint16_t *other) const { return static_cast<uint16_t *>(*this) == other; }
UBool operator!=(const uint16_t *other) const { return !operator==(other); }
#if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
UBool operator==(const wchar_t *other) const { return static_cast<wchar_t *>(*this) == other; }
UBool operator!=(const wchar_t *other) const { return !operator==(other); }
#endif
UBool operator==(const std::nullptr_t null) const { return get() == null; }
UBool operator!=(const std::nullptr_t null) const { return !operator==(null); }
/**
* Comparison with NULL.
* @return TRUE if the pointer is nullptr and null==0
* @draft ICU 59
*/
UBool operator==(int null) const { return get() == nullptr && null == 0; }
/**
* Comparison with NULL.
* @return TRUE if the pointer is not nullptr and null==0
* @draft ICU 59
*/
UBool operator!=(int null) const { return get() != nullptr && null == 0; }
Char16Ptr operator+(size_t offset) const { return Char16Ptr(get() + offset); }
private:
Char16Ptr() = delete;
#ifdef U_ALIASING_BARRIER
template<typename T> char16_t *cast(T *t) {
template<typename T> static char16_t *cast(T *t) {
U_ALIASING_BARRIER(t);
return reinterpret_cast<char16_t *>(t);
}
@ -144,8 +194,22 @@ Char16Ptr::Char16Ptr(uint16_t *p) : p(cast(p)) {}
Char16Ptr::Char16Ptr(wchar_t *p) : p(cast(p)) {}
#endif
Char16Ptr::Char16Ptr(std::nullptr_t p) : p(p) {}
Char16Ptr::~Char16Ptr() {
U_ALIASING_BARRIER(p);
}
char16_t *Char16Ptr::get() { return p; }
char16_t *Char16Ptr::get() const { return p; }
Char16Ptr::operator uint16_t *() const {
U_ALIASING_BARRIER(p);
return reinterpret_cast<uint16_t *>(p);
}
#if U_SIZEOF_WCHAR_T==2
Char16Ptr::operator wchar_t *() const {
U_ALIASING_BARRIER(p);
return reinterpret_cast<wchar_t *>(p);
}
#endif
#else
@ -155,8 +219,18 @@ Char16Ptr::Char16Ptr(uint16_t *p) { u.up = p; }
Char16Ptr::Char16Ptr(wchar_t *p) { u.wp = p; }
#endif
Char16Ptr::Char16Ptr(std::nullptr_t p) { u.cp = p; }
Char16Ptr::~Char16Ptr() {}
char16_t *Char16Ptr::get() { return u.cp; }
char16_t *Char16Ptr::get() const { return u.cp; }
Char16Ptr::operator uint16_t *() const {
return u.up;
}
#if U_SIZEOF_WCHAR_T==2
Char16Ptr::operator wchar_t *() const {
return u.wp;
}
#endif
#endif
@ -196,22 +270,60 @@ public:
* @draft ICU 59
*/
ConstChar16Ptr(int null);
/**
* Destructor.
* @draft ICU 59
*/
inline ~ConstChar16Ptr();
/**
* Pointer access.
* @draft ICU 59
*/
inline const char16_t *get() const;
/**
* Pointer access via type conversion (e.g., static_cast).
* char16_t pointer access via type conversion (e.g., static_cast).
* @draft ICU 59
*/
operator const char16_t *() { return get(); }
operator const char16_t *() const { return get(); }
/**
* uint16_t pointer access via type conversion (e.g., static_cast).
* @draft ICU 59
*/
inline operator const uint16_t *() const;
#if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
/**
* wchar_t pointer access via type conversion (e.g., static_cast).
* @draft ICU 59
*/
inline operator const wchar_t *() const;
#endif
operator const void *() const { return get(); }
char16_t operator[](size_t offset) const { return get()[offset]; }
UBool operator==(const ConstChar16Ptr &other) const { return get() == other.get(); }
UBool operator!=(const ConstChar16Ptr &other) const { return !operator==(other); }
UBool operator==(const char16_t *other) const { return get() == other; }
UBool operator!=(const char16_t *other) const { return !operator==(other); }
UBool operator==(const uint16_t *other) const { return static_cast<const uint16_t *>(*this) == other; }
UBool operator!=(const uint16_t *other) const { return !operator==(other); }
#if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
UBool operator==(const wchar_t *other) const { return static_cast<const wchar_t *>(*this) == other; }
UBool operator!=(const wchar_t *other) const { return !operator==(other); }
#endif
UBool operator==(const std::nullptr_t null) const { return get() == null; }
UBool operator!=(const std::nullptr_t null) const { return !operator==(null); }
UBool operator==(int null) const { return get() == nullptr && null == 0; }
UBool operator!=(int null) const { return get() != nullptr && null == 0; }
ConstChar16Ptr operator+(size_t offset) { return ConstChar16Ptr(get() + offset); }
private:
ConstChar16Ptr() = delete;
#ifdef U_ALIASING_BARRIER
template<typename T> const char16_t *cast(const T *t) {
template<typename T> static const char16_t *cast(const T *t) {
U_ALIASING_BARRIER(t);
return reinterpret_cast<const char16_t *>(t);
}
@ -234,9 +346,23 @@ ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) : p(cast(p)) {}
ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) : p(cast(p)) {}
#endif
ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) : p(p) {}
ConstChar16Ptr::~ConstChar16Ptr() {
U_ALIASING_BARRIER(p);
}
const char16_t *ConstChar16Ptr::get() const { return p; }
ConstChar16Ptr::operator const uint16_t *() const {
U_ALIASING_BARRIER(p);
return reinterpret_cast<const uint16_t *>(p);
}
#if U_SIZEOF_WCHAR_T==2
ConstChar16Ptr::operator const wchar_t *() const {
U_ALIASING_BARRIER(p);
return reinterpret_cast<const wchar_t *>(p);
}
#endif
#else
ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) { u.cp = p; }
@ -245,9 +371,19 @@ ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) { u.up = p; }
ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) { u.wp = p; }
#endif
ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) { u.cp = p; }
ConstChar16Ptr::~ConstChar16Ptr() {}
const char16_t *ConstChar16Ptr::get() const { return u.cp; }
ConstChar16Ptr::operator const uint16_t *() const {
return u.up;
}
#if U_SIZEOF_WCHAR_T==2
ConstChar16Ptr::operator const wchar_t *() const {
return u.wp;
}
#endif
#endif
// TODO end experiment -----------------
@ -3047,13 +3183,13 @@ public:
* in the buffer, starting at the returned pointer;
* default to the current string capacity if minCapacity==-1
* @return a writable pointer to the internal string buffer,
* or 0 if an error occurs (nested calls, out of memory)
* or nullptr if an error occurs (nested calls, out of memory)
*
* @see releaseBuffer
* @see getTerminatedBuffer()
* @stable ICU 2.0
*/
UChar *getBuffer(int32_t minCapacity);
Char16Ptr getBuffer(int32_t minCapacity);
/**
* Release a read/write buffer on a UnicodeString object with an
@ -3101,13 +3237,13 @@ public:
* be modified.
*
* @return a read-only pointer to the internal string buffer,
* or 0 if the string is empty or bogus
* or nullptr if the string is empty or bogus
*
* @see getBuffer(int32_t minCapacity)
* @see getTerminatedBuffer()
* @stable ICU 2.0
*/
inline const UChar *getBuffer() const;
inline ConstChar16Ptr getBuffer() const;
/**
* Get a read-only pointer to the internal buffer,
@ -3142,7 +3278,7 @@ public:
* @see getBuffer()
* @stable ICU 2.2
*/
const UChar *getTerminatedBuffer();
ConstChar16Ptr getTerminatedBuffer();
//========================================
// Constructors
@ -4134,7 +4270,7 @@ UnicodeString::isBufferWritable() const
(!(fUnion.fFields.fLengthAndFlags&kRefCounted) || refCount()==1));
}
inline const UChar *
inline ConstChar16Ptr
UnicodeString::getBuffer() const {
if(fUnion.fFields.fLengthAndFlags&(kIsBogus|kOpenGetBuffer)) {
return 0;

View File

@ -260,9 +260,10 @@ UnicodeString::UnicodeString(const UChar *text,
}
UnicodeString::UnicodeString(UBool isTerminated,
ConstChar16Ptr text,
ConstChar16Ptr textPtr,
int32_t textLength) {
fUnion.fFields.fLengthAndFlags = kReadonlyAlias;
const UChar *text = textPtr;
if(text == NULL) {
// treat as an empty string, do not alias
setToEmpty();
@ -276,7 +277,7 @@ UnicodeString::UnicodeString(UBool isTerminated,
// text is terminated, or else it would have failed the above test
textLength = u_strlen(text);
}
setArray(const_cast<UChar *>(text.get()), textLength,
setArray(const_cast<UChar *>(text), textLength,
isTerminated ? textLength + 1 : textLength);
}
}
@ -916,10 +917,11 @@ UnicodeString::doExtract(int32_t start,
}
int32_t
UnicodeString::extract(Char16Ptr dest, int32_t destCapacity,
UnicodeString::extract(Char16Ptr destPtr, int32_t destCapacity,
UErrorCode &errorCode) const {
int32_t len = length();
if(U_SUCCESS(errorCode)) {
UChar *dest = destPtr;
if(isBogus() || destCapacity<0 || (destCapacity>0 && dest==0)) {
errorCode=U_ILLEGAL_ARGUMENT_ERROR;
} else {
@ -1258,7 +1260,7 @@ UnicodeString::unBogus() {
}
}
const UChar *
ConstChar16Ptr
UnicodeString::getTerminatedBuffer() {
if(!isWritable()) {
return 0;
@ -1292,7 +1294,7 @@ UnicodeString::getTerminatedBuffer() {
array[len] = 0;
return array;
} else {
return NULL;
return nullptr;
}
}
@ -1756,7 +1758,7 @@ UnicodeString::doHashCode() const
// External Buffer
//========================================
UChar *
Char16Ptr
UnicodeString::getBuffer(int32_t minCapacity) {
if(minCapacity>=-1 && cloneArrayIfNeeded(minCapacity)) {
fUnion.fFields.fLengthAndFlags|=kOpenGetBuffer;

View File

@ -290,7 +290,7 @@ static int printConverters(const char *pname, const char *lookfor,
UnicodeString str(name, "");
putchar('\t');
u_wmsg(stderr, "cantGetAliases", str.getTerminatedBuffer(),
u_wmsg(stderr, "cantGetAliases", str.getTerminatedBuffer().get(),
u_wmsg_errorName(err));
goto error_cleanup;
} else {
@ -304,7 +304,7 @@ static int printConverters(const char *pname, const char *lookfor,
if (U_FAILURE(err)) {
UnicodeString str(name, "");
putchar('\t');
u_wmsg(stderr, "cantGetAliases", str.getTerminatedBuffer(),
u_wmsg(stderr, "cantGetAliases", str.getTerminatedBuffer().get(),
u_wmsg_errorName(err));
goto error_cleanup;
}
@ -627,7 +627,7 @@ ConvertFile::convertFile(const char *pname,
UnicodeString str2(strerror(errno), "");
str2.append((UChar32) 0);
initMsg(pname);
u_wmsg(stderr, "cantOpenInputF", str1.getBuffer(), str2.getBuffer());
u_wmsg(stderr, "cantOpenInputF", str1.getBuffer().get(), str2.getBuffer().get());
return FALSE;
}
closeFile = TRUE;
@ -672,10 +672,10 @@ ConvertFile::convertFile(const char *pname,
UChar linebuf[20], offsetbuf[20];
uprv_itou(linebuf, 20, parse.line, 10, 0);
uprv_itou(offsetbuf, 20, parse.offset, 10, 0);
u_wmsg(stderr, "cantCreateTranslitParseErr", str.getTerminatedBuffer(),
u_wmsg(stderr, "cantCreateTranslitParseErr", str.getTerminatedBuffer().get(),
u_wmsg_errorName(err), linebuf, offsetbuf);
} else {
u_wmsg(stderr, "cantCreateTranslit", str.getTerminatedBuffer(),
u_wmsg(stderr, "cantCreateTranslit", str.getTerminatedBuffer().get(),
u_wmsg_errorName(err));
}
@ -698,7 +698,7 @@ ConvertFile::convertFile(const char *pname,
if (U_FAILURE(err)) {
UnicodeString str(fromcpage, "");
initMsg(pname);
u_wmsg(stderr, "cantOpenFromCodeset", str.getTerminatedBuffer(),
u_wmsg(stderr, "cantOpenFromCodeset", str.getTerminatedBuffer().get(),
u_wmsg_errorName(err));
goto error_exit;
}
@ -713,7 +713,7 @@ ConvertFile::convertFile(const char *pname,
if (U_FAILURE(err)) {
UnicodeString str(tocpage, "");
initMsg(pname);
u_wmsg(stderr, "cantOpenToCodeset", str.getTerminatedBuffer(),
u_wmsg(stderr, "cantOpenToCodeset", str.getTerminatedBuffer().get(),
u_wmsg_errorName(err));
goto error_exit;
}
@ -742,7 +742,7 @@ ConvertFile::convertFile(const char *pname,
if (ferror(infile) != 0) {
UnicodeString str(strerror(errno));
initMsg(pname);
u_wmsg(stderr, "cantRead", str.getTerminatedBuffer());
u_wmsg(stderr, "cantRead", str.getTerminatedBuffer().get());
goto error_exit;
}
@ -819,8 +819,8 @@ ConvertFile::convertFile(const char *pname,
initMsg(pname);
u_wmsg(stderr, "problemCvtToU",
UnicodeString(pos, length, "").getTerminatedBuffer(),
str.getTerminatedBuffer(),
UnicodeString(pos, length, "").getTerminatedBuffer().get(),
str.getTerminatedBuffer().get(),
u_wmsg_errorName(err));
willexit = TRUE;
@ -1008,10 +1008,10 @@ ConvertFile::convertFile(const char *pname,
initMsg(pname);
u_wmsg(stderr, errtag,
UnicodeString(pos, length, "").getTerminatedBuffer(),
str.getTerminatedBuffer(),
UnicodeString(pos, length, "").getTerminatedBuffer().get(),
str.getTerminatedBuffer().get(),
u_wmsg_errorName(err));
u_wmsg(stderr, "errorUnicode", str.getTerminatedBuffer());
u_wmsg(stderr, "errorUnicode", str.getTerminatedBuffer().get());
willexit = TRUE;
err = U_ZERO_ERROR; /* reset the error for the rest of the conversion. */
@ -1026,7 +1026,7 @@ ConvertFile::convertFile(const char *pname,
if (wr != outlen) {
UnicodeString str(strerror(errno));
initMsg(pname);
u_wmsg(stderr, "cantWrite", str.getTerminatedBuffer());
u_wmsg(stderr, "cantWrite", str.getTerminatedBuffer().get());
willexit = TRUE;
}
@ -1075,7 +1075,7 @@ static void usage(const char *pname, int ecode) {
UnicodeString upname(pname, (int32_t)(uprv_strlen(pname) + 1));
UnicodeString mname(msg, msgLen + 1);
res = u_wmsg(fp, "usage", mname.getBuffer(), upname.getBuffer());
res = u_wmsg(fp, "usage", mname.getBuffer().get(), upname.getBuffer().get());
if (!ecode) {
if (!res) {
fputc('\n', fp);
@ -1184,7 +1184,7 @@ main(int argc, char **argv)
initMsg(pname);
UnicodeString str(*iter);
initMsg(pname);
u_wmsg(stderr, "badBlockSize", str.getTerminatedBuffer());
u_wmsg(stderr, "badBlockSize", str.getTerminatedBuffer().get());
return 3;
}
} else {
@ -1212,7 +1212,7 @@ main(int argc, char **argv)
if (U_FAILURE(e) || !printName) {
UnicodeString str(*iter);
initMsg(pname);
u_wmsg(stderr, "noSuchCodeset", str.getTerminatedBuffer());
u_wmsg(stderr, "noSuchCodeset", str.getTerminatedBuffer().get());
return 2;
}
} else
@ -1240,7 +1240,7 @@ main(int argc, char **argv)
} else {
UnicodeString str(*iter);
initMsg(pname);
u_wmsg(stderr, "unknownCallback", str.getTerminatedBuffer());
u_wmsg(stderr, "unknownCallback", str.getTerminatedBuffer().get());
return 4;
}
} else {
@ -1256,7 +1256,7 @@ main(int argc, char **argv)
} else {
UnicodeString str(*iter);
initMsg(pname);
u_wmsg(stderr, "unknownCallback", str.getTerminatedBuffer());
u_wmsg(stderr, "unknownCallback", str.getTerminatedBuffer().get());
return 4;
}
} else {
@ -1276,7 +1276,7 @@ main(int argc, char **argv)
} else {
UnicodeString str(*iter);
initMsg(pname);
u_wmsg(stderr, "unknownCallback", str.getTerminatedBuffer());
u_wmsg(stderr, "unknownCallback", str.getTerminatedBuffer().get());
return 4;
}
} else {
@ -1329,7 +1329,7 @@ main(int argc, char **argv)
UnicodeString str2(strerror(errno), "");
initMsg(pname);
u_wmsg(stderr, "cantCreateOutputF",
str1.getBuffer(), str2.getBuffer());
str1.getBuffer().get(), str2.getBuffer().get());
return 1;
}
} else {

View File

@ -37,7 +37,7 @@ public:
UBool forData(const CollationData &data, UErrorCode &errorCode);
const uint16_t *getTable() const {
return reinterpret_cast<const uint16_t *>(result.getBuffer());
return result.getBuffer();
}
int32_t lengthOfTable() const { return result.length(); }

View File

@ -121,7 +121,9 @@ void DateFormatRoundTripTest::TestCentury()
*/
//if (date[1] != date[2] || result[0] != result[1]) {
if (date[1] != date[2]) {
errln("Round trip failure: \"%S\" (%f), \"%S\" (%f)", result[0].getBuffer(), date[1], result[1].getBuffer(), date[2]);
errln("Round trip failure: \"%S\" (%f), \"%S\" (%f)",
static_cast<const UChar *>(result[0].getBuffer()), date[1],
static_cast<const UChar *>(result[1].getBuffer()), date[2]);
}
}

View File

@ -1087,7 +1087,7 @@ UnicodeStringTest::TestMiscellaneous()
}
// test releaseBuffer() with a NUL-terminated buffer
test1.getBuffer(20)[2]=0;
test1.getBuffer(20).get()[2]=0;
test1.releaseBuffer(); // implicit -1
if(test1.length()!=2 || test1.charAt(0)!=1 || test1.charAt(1) !=2) {
errln("UnicodeString::releaseBuffer(-1) does not properly set the length of the UnicodeString");
@ -1558,7 +1558,10 @@ UnicodeStringTest::TestBogus() {
// writable alias to another string's buffer: very bad idea, just convenient for this test
test3.setToBogus();
if(!test3.isBogus() || test3.setTo((UChar *)test1.getBuffer(), test1.length(), test1.getCapacity()).isBogus() || test3!=test1) {
if(!test3.isBogus() ||
test3.setTo(const_cast<UChar *>(test1.getBuffer().get()),
test1.length(), test1.getCapacity()).isBogus() ||
test3!=test1) {
errln("bogus.setTo(writable alias) failed");
}

View File

@ -1031,7 +1031,7 @@ void SRBRoot::write(const char *outputDir, const char *outputPkg,
if (f16BitUnits.length() <= 1) {
// no pool strings to checksum
} else if (U_IS_BIG_ENDIAN) {
checksum = computeCRC((const char *)f16BitUnits.getBuffer(),
checksum = computeCRC(reinterpret_cast<const char *>(f16BitUnits.getBuffer().get()),
(uint32_t)f16BitUnits.length() * 2, checksum);
} else {
// Swap to big-endian so we get the same checksum on all platforms
@ -1039,7 +1039,7 @@ void SRBRoot::write(const char *outputDir, const char *outputPkg,
UnicodeString s(f16BitUnits);
s.append((UChar)1); // Ensure that we own this buffer.
assert(!s.isBogus());
uint16_t *p = (uint16_t *)s.getBuffer();
uint16_t *p = const_cast<uint16_t *>(static_cast<const uint16_t *>(s.getBuffer()));
for (int32_t count = f16BitUnits.length(); count > 0; --count) {
uint16_t x = *p;
*p++ = (uint16_t)((x << 8) | (x >> 8));