/*
*******************************************************************************
-* Copyright (C) 1997-2012, International Business Machines Corporation and *
+* Copyright (C) 1997-2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
#include "unicode/ustring.h"
#include "unicode/measure.h"
#include "unicode/curramt.h"
+#include "unicode/uformattable.h"
#include "charstr.h"
#include "cmemory.h"
#include "cstring.h"
return "";
}
if (fDecimalStr != NULL) {
- return fDecimalStr->toStringPiece();
+ return fDecimalStr->toStringPiece();
}
- if (fDecimalNum == NULL) {
+ CharString *decimalStr = internalGetCharString(status);
+ if(decimalStr == NULL) {
+ return ""; // getDecimalNumber returns "" for error cases
+ } else {
+ return decimalStr->toStringPiece();
+ }
+}
+
+CharString *Formattable::internalGetCharString(UErrorCode &status) {
+ if(fDecimalStr == NULL) {
+ if (fDecimalNum == NULL) {
// No decimal number for the formattable yet. Which means the value was
// set directly by the user as an int, int64 or double. If the value came
// from parsing, or from the user setting a decimal number, fDecimalNum
// would already be set.
//
- fDecimalNum = new DigitList; // TODO: use internal digit list
+ fDecimalNum = new DigitList; // TODO: use internal digit list
if (fDecimalNum == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return "";
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
}
switch (fType) {
case kDouble:
- fDecimalNum->set(this->getDouble());
- break;
+ fDecimalNum->set(this->getDouble());
+ break;
case kLong:
- fDecimalNum->set(this->getLong());
- break;
+ fDecimalNum->set(this->getLong());
+ break;
case kInt64:
- fDecimalNum->set(this->getInt64());
- break;
+ fDecimalNum->set(this->getInt64());
+ break;
default:
- // The formattable's value is not a numeric type.
- status = U_INVALID_STATE_ERROR;
- return "";
+ // The formattable's value is not a numeric type.
+ status = U_INVALID_STATE_ERROR;
+ return NULL;
}
- }
+ }
- fDecimalStr = new CharString;
- if (fDecimalStr == NULL) {
+ fDecimalStr = new CharString;
+ if (fDecimalStr == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
- return "";
+ return NULL;
+ }
+ fDecimalNum->getDecimal(*fDecimalStr, status);
}
- fDecimalNum->getDecimal(*fDecimalStr, status);
-
- return fDecimalStr->toStringPiece();
+ return fDecimalStr;
}
#endif
+/* ---- UFormattable stuff ---- */
+
+
+U_DRAFT UFormattable* U_EXPORT2
+ufmt_open(UErrorCode *status) {
+ if( U_FAILURE(*status) ) {
+ return NULL;
+ }
+ UFormattable *fmt = (new Formattable())->toUFormattable();
+
+ if( fmt == NULL ) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ }
+ return fmt;
+}
+
+U_DRAFT void U_EXPORT2
+ufmt_close(UFormattable *fmt) {
+ Formattable *obj = Formattable::fromUFormattable(fmt);
+
+ delete obj;
+}
+
+U_INTERNAL UFormattableType U_EXPORT2
+ufmt_getType(UFormattable *fmt, UErrorCode *status) {
+ if(U_FAILURE(*status)) {
+ return (UFormattableType)-1;
+ }
+ Formattable *obj = Formattable::fromUFormattable(fmt);
+ switch( obj->getType() ) {
+ case Formattable::kDate:
+ return UFMT_DATE;
+ break;
+ case Formattable::kDouble:
+ return UFMT_DOUBLE;
+ break;
+ case Formattable::kLong:
+ return UFMT_LONG;
+ break;
+ case Formattable::kString:
+ return UFMT_STRING;
+ break;
+ case Formattable::kArray:
+ return UFMT_ARRAY;
+ break;
+ case Formattable::kInt64:
+ return UFMT_INT64;
+ break;
+ case Formattable::kObject:
+ return UFMT_OBJECT;
+ break;
+ default:
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return (UFormattableType)-1; // invalid
+ }
+}
+
+
+U_INTERNAL UBool U_EXPORT2
+ufmt_isNumeric(UFormattable *fmt) {
+ Formattable *obj = Formattable::fromUFormattable(fmt);
+ return obj->isNumeric();
+}
+
+U_DRAFT UDate U_EXPORT2
+ufmt_getDate(UFormattable *fmt, UErrorCode *status) {
+ Formattable *obj = Formattable::fromUFormattable(fmt);
+
+ return obj->getDate(*status);
+}
+
+U_DRAFT double U_EXPORT2
+ufmt_getDouble(UFormattable *fmt, UErrorCode *status) {
+ Formattable *obj = Formattable::fromUFormattable(fmt);
+
+ return obj->getDouble(*status);
+}
+
+U_DRAFT int32_t U_EXPORT2
+ufmt_getLong(UFormattable *fmt, UErrorCode *status) {
+ Formattable *obj = Formattable::fromUFormattable(fmt);
+
+ return obj->getLong(*status);
+}
+
+
+U_DRAFT const void *U_EXPORT2
+ufmt_getObject(UFormattable *fmt, UErrorCode *status) {
+ Formattable *obj = Formattable::fromUFormattable(fmt);
+
+ const void *ret = obj->getObject();
+ if( ret==NULL &&
+ (obj->getType() != Formattable::kObject) &&
+ U_SUCCESS( *status )) {
+ *status = U_INVALID_FORMAT_ERROR;
+ }
+ return ret;
+}
+
+U_DRAFT const UChar* U_EXPORT2
+ufmt_getUChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
+ Formattable *obj = Formattable::fromUFormattable(fmt);
+
+ // avoid bogosity by checking the type first.
+ if( obj->getType() != Formattable::kString ) {
+ if( U_SUCCESS(*status) ){
+ *status = U_INVALID_FORMAT_ERROR;
+ }
+ return NULL;
+ }
+
+ // This should return a valid string
+ UnicodeString &str = obj->getString(*status);
+ if( U_SUCCESS(*status) && len != NULL ) {
+ *len = str.length();
+ }
+ return str.getTerminatedBuffer();
+}
+
+U_DRAFT int32_t U_EXPORT2
+ufmt_getArrayLength(UFormattable* fmt, UErrorCode *status) {
+ Formattable *obj = Formattable::fromUFormattable(fmt);
+
+ int32_t count;
+ (void)obj->getArray(count, *status);
+ return count;
+}
+
+U_DRAFT UFormattable * U_EXPORT2
+ufmt_getArrayItemByIndex(UFormattable* fmt, int32_t n, UErrorCode *status) {
+ Formattable *obj = Formattable::fromUFormattable(fmt);
+ int32_t count;
+ (void)obj->getArray(count, *status);
+ if(U_FAILURE(*status)) {
+ return NULL;
+ } else if(n<0 || n>=count) {
+ setError(*status, U_INDEX_OUTOFBOUNDS_ERROR);
+ return NULL;
+ } else {
+ return (*obj)[n].toUFormattable(); // returns non-const Formattable
+ }
+}
+
+U_DRAFT const char * U_EXPORT2
+ufmt_getDecNumChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
+ if(U_FAILURE(*status)) {
+ return "";
+ }
+ Formattable *obj = Formattable::fromUFormattable(fmt);
+ CharString *charString = obj->internalGetCharString(*status);
+ if(U_FAILURE(*status)) {
+ return "";
+ }
+ if(charString == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return "";
+ } else {
+ if(len!=NULL) {
+ *len = charString->length();
+ }
+ return charString->data();
+ }
+}
+
+// make-a-copy version
+// U_DRAFT int32_t U_EXPORT2
+// ufmt_getDecNumChars(UFormattable *fmt, char *buf, int32_t len, UErrorCode *status) {
+// if(U_FAILURE(*status)) {
+// return 0;
+// }
+// Formattable *obj = Formattable::fromUFormattable(fmt);
+// CharString *charString = obj->internalGetCharString(*status);
+// if(U_FAILURE(*status)) {
+// return 0;
+// }
+// if(charString == NULL) {
+// *status = U_MEMORY_ALLOCATION_ERROR;
+// return 0;
+// } else {
+// return charString->extract(buf, len, *status);
+// }
+// }
+
+
+U_DRAFT int64_t U_EXPORT2
+ufmt_getInt64(UFormattable *fmt, UErrorCode *status) {
+ Formattable *obj = Formattable::fromUFormattable(fmt);
+ return obj->getInt64(*status);
+}
+
+
U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */
-<?xml version="1.0" encoding="utf-8"?>\r
+<?xml version="1.0" encoding="utf-8"?>\r
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
<ItemGroup Label="ProjectConfigurations">\r
<ProjectConfiguration Include="Debug|Win32">\r
</Command>\r
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>\r
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode\r
+</Command>\r
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>\r
+ </CustomBuild>\r
+ <CustomBuild Include="unicode\uformattable.h">\r
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode\r
+</Command>\r
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>\r
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode\r
+</Command>\r
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>\r
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode\r
+</Command>\r
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>\r
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode\r
</Command>\r
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>\r
</CustomBuild>\r
#define FMTABLE_H
#include "unicode/utypes.h"
-#include "unicode/unistr.h"
-#include "unicode/stringpiece.h"
/**
- * \file
- * \brief C++ API: Formattable is a thin wrapper for primitive numeric types.
+ * \file
+ * \brief C++ API: Formattable is a thin wrapper for primitive types used for formatting and parsing
*/
#if !UCONFIG_NO_FORMATTING
+#include "unicode/unistr.h"
+#include "unicode/stringpiece.h"
+#include "unicode/uformattable.h"
+
U_NAMESPACE_BEGIN
class CharString;
* Creates a Formattable object with a UDate instance.
* @param d the UDate instance.
* @param flag the flag to indicate this is a date. Always set it to kIsDate
- * @stable ICU 2.0
+ * @stable ICU 2.0
*/
Formattable(UDate d, ISDATE flag);
* @stable ICU 2.0
*/
UBool operator==(const Formattable &other) const;
-
- /**
+
+ /**
* Equality operator.
* @param other the object to be compared with.
* @return TRUE if other are unequal to this, FALSE otherwise.
UBool operator!=(const Formattable& other) const
{ return !operator==(other); }
- /**
+ /**
* Destructor.
* @stable ICU 2.0
*/
*/
Formattable *clone() const;
- /**
+ /**
* Selector for flavor of data type contained within a
* Formattable object. Formattable is a union of several
* different types, and at any time contains exactly one type.
* @stable ICU 2.0
*/
Type getType(void) const;
-
+
/**
* Returns TRUE if the data type of this Formattable object
* is kDouble, kLong, kInt64 or kDecimalNumber.
* @stable ICU 3.0
*/
UBool isNumeric() const;
-
+
/**
* Gets the double value of this object. If this object is not of type
* kDouble then the result is undefined.
* @return the double value of this object.
* @stable ICU 2.0
- */
+ */
double getDouble(void) const { return fValue.fDouble; }
/**
* @param status the error code
* @return the double value of this object.
* @stable ICU 3.0
- */
+ */
double getDouble(UErrorCode& status) const;
/**
* kLong then the result is undefined.
* @return the long value of this object.
* @stable ICU 2.0
- */
+ */
int32_t getLong(void) const { return (int32_t)fValue.fInt64; }
/**
* @param status the error code
* @return the long value of this object.
* @stable ICU 3.0
- */
+ */
int32_t getLong(UErrorCode& status) const;
/**
* kInt64 then the result is undefined.
* @return the int64 value of this object.
* @stable ICU 2.8
- */
+ */
int64_t getInt64(void) const { return fValue.fInt64; }
/**
* @param status the error code
* @return the int64 value of this object.
* @stable ICU 3.0
- */
+ */
int64_t getInt64(UErrorCode& status) const;
/**
* kDate then the result is undefined.
* @return the Date value of this object.
* @stable ICU 2.0
- */
+ */
UDate getDate() const { return fValue.fDate; }
/**
* @param status the error code.
* @return the Date value of this object.
* @stable ICU 3.0
- */
+ */
UDate getDate(UErrorCode& status) const;
/**
* @param result Output param to receive the Date value of this object.
* @return A reference to 'result'.
* @stable ICU 2.0
- */
+ */
UnicodeString& getString(UnicodeString& result) const
{ result=*fValue.fString; return result; }
* string, status is set to U_INVALID_FORMAT_ERROR and a bogus
* string is returned.
* @param result Output param to receive the Date value of this object.
- * @param status the error code.
+ * @param status the error code.
* @return A reference to 'result'.
* @stable ICU 3.0
- */
+ */
UnicodeString& getString(UnicodeString& result, UErrorCode& status) const;
/**
* Gets a reference to the string value of this object. If the
* type is not a string, status is set to U_INVALID_FORMAT_ERROR
* and the result is a bogus string.
- * @param status the error code.
+ * @param status the error code.
* @return a reference to the string value of this object.
* @stable ICU 3.0
*/
* @param count fill-in with the count of this object.
* @return the array value of this object.
* @stable ICU 2.0
- */
+ */
const Formattable* getArray(int32_t& count) const
{ count=fValue.fArrayAndCount.fCount; return fValue.fArrayAndCount.fArray; }
* not an array, status is set to U_INVALID_FORMAT_ERROR, count is
* set to 0, and the result is NULL.
* @param count fill-in with the count of this object.
- * @param status the error code.
+ * @param status the error code.
* @return the array value of this object.
* @stable ICU 3.0
- */
+ */
const Formattable* getArray(int32_t& count, UErrorCode& status) const;
/**
* @stable ICU 2.0
*/
Formattable& operator[](int32_t index) { return fValue.fArrayAndCount.fArray[index]; }
-
+
/**
* Returns a pointer to the UObject contained within this
* formattable, or NULL if this object does not contain a UObject.
* For values obtained by parsing, the returned decimal number retains
* the full precision and range of the original input, unconstrained by
* the limits of a double floating point or a 64 bit int.
- *
+ *
* This function is not thread safe, and therfore is not declared const,
* even though it is logically const.
*
* kDouble.
* @param d the new double value to be set.
* @stable ICU 2.0
- */
+ */
void setDouble(double d);
/**
* kLong.
* @param l the new long value to be set.
* @stable ICU 2.0
- */
+ */
void setLong(int32_t l);
/**
* kInt64.
* @param ll the new int64 value to be set.
* @stable ICU 2.8
- */
+ */
void setInt64(int64_t ll);
/**
* kDate.
* @param d the new Date value to be set.
* @stable ICU 2.0
- */
+ */
void setDate(UDate d);
/**
* kString.
* @param stringToCopy the new string value to be set.
* @stable ICU 2.0
- */
+ */
void setString(const UnicodeString& stringToCopy);
/**
* @param array the array value.
* @param count the number of array elements to be copied.
* @stable ICU 2.0
- */
+ */
void setArray(const Formattable* array, int32_t count);
/**
* changes the type to kArray.
* @param stringToAdopt the new string value to be adopted.
* @stable ICU 2.0
- */
+ */
void adoptString(UnicodeString* stringToAdopt);
/**
* Sets and adopts the array value and count of this object and
* changes the type to kArray.
* @stable ICU 2.0
- */
+ */
void adoptArray(Formattable* array, int32_t count);
-
+
/**
* Sets and adopts the UObject value of this object and changes
* the type to kObject. After this call, the caller must not
/**
* Sets the the numeric value from a decimal number string, and changes
- * the type to to a numeric type appropriate for the number.
+ * the type to to a numeric type appropriate for the number.
* The syntax of the number is a "numeric string"
* as defined in the Decimal Arithmetic Specification, available at
* http://speleotrove.com/decimal
*/
static UClassID U_EXPORT2 getStaticClassID();
+ /**
+ * Convert the UFormattable to a Formattable. Internally, this is a reinterpret_cast.
+ * @param fmt a valid UFormattable
+ * @return the UFormattable as a Formattable object pointer. This is an alias to the original
+ * UFormattable, and so is only valid while the original argument remains in scope.
+ * @draft ICU 52
+ */
+ static inline Formattable *fromUFormattable(UFormattable *fmt);
+
+ /**
+ * Convert this object pointer to a UFormattable.
+ * @return this object as a UFormattable pointer. This is an alias to the original UFormattable,
+ * and so is only valid while the original argument remains in scope.
+ */
+ inline UFormattable *toUFormattable();
+
#ifndef U_HIDE_DEPRECATED_API
/**
* Deprecated variant of getLong(UErrorCode&).
* @param status the error code
* @return the long value of this object.
* @deprecated ICU 3.0 use getLong(UErrorCode&) instead
- */
+ */
inline int32_t getLong(UErrorCode* status) const;
#endif /* U_HIDE_DEPRECATED_API */
* @internal
*/
void adoptDigitList(DigitList *dl);
+
+ /**
+ * Internal function to return the CharString pointer.
+ * @param status error code
+ * @return pointer to the CharString - may become invalid if the object is modified
+ */
+ CharString *internalGetCharString(UErrorCode &status);
+
#endif /* U_HIDE_INTERNAL_API */
private:
return getLong(*status);
}
+inline UFormattable* Formattable::toUFormattable() {
+ return (UFormattable*)(this);
+}
+
+inline Formattable* Formattable::fromUFormattable(UFormattable *fmt) {
+ return reinterpret_cast<Formattable *>(fmt);
+}
+
U_NAMESPACE_END
--- /dev/null
+/*
+TODO
+* copy C++ apidoc concerning error codes to appropriate wrapper functions
+*/
+
+
+/*
+********************************************************************************
+* Copyright (C) 2013, International Business Machines Corporation and others.
+* All Rights Reserved.
+********************************************************************************
+*
+* File UFORMATTABLE.H
+*
+* Modification History:
+*
+* Date Name Description
+* 2013 Jul 7 srl New
+********************************************************************************
+*/
+
+/**
+ * \file
+ * \brief C API: UFormattable is a thin wrapper for primitive types used for formatting and parsing.
+ *
+ * This is a C interface to the icu::Formattable class. Static functions on this class convert
+ * to and from this interface (via reinterpret_cast). Note that Formattables (and thus UFormattables)
+ * are mutable, and many operations (even getters) may actually modify the internal state. For this
+ * reason, UFormattables are not thread safe, and should not be shared between threads.
+ */
+
+#ifndef FORMATTABLE_H
+#define FORMATTABLE_H
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/localpointer.h"
+
+/**
+ * Enum designating the type of a UFormattable instance.
+ * Practically, this indicates which of the getters would return without conversion
+ * or error.
+ * @see icu::Formattable::Type
+ * @draft ICU 52
+ */
+typedef enum UFormattableType {
+ UFMT_DATE = 0, /**< ufmt_getDate() will return without conversion. */
+ UFMT_DOUBLE, /**< ufmt_getDouble() will return without conversion. */
+ UFMT_LONG, /**< ufmt_getLong() will return without conversion. */
+ UFMT_INT64, /**< ufmt_getInt64() will return without conversion. */
+ UFMT_OBJECT, /**< ufmt_getObject() will return without conversion. */
+ UFMT_STRING, /**< ufmt_getUChars() will return without conversion. */
+ UFMT_ARRAY, /**< ufmt_countArray() and ufmt_getArray() will return the value. */
+ UFMT_COUNT /**< Count of defined UFormattableType values */
+} UFormattableType;
+
+
+/**
+ * Opaque type representing various types of data which may be used for formatting
+ * and parsing operations.
+ * @see icu::Formattable
+ * @draft ICU 52
+ */
+typedef void *UFormattable;
+
+/**
+ * Initialize a UFormattable, to type UNUM_LONG, value 0
+ * may return error if memory allocation failed.
+ * parameter status error code.
+ * @draft ICU 52
+ * @return the new UFormattable
+ */
+U_DRAFT UFormattable* U_EXPORT2
+ufmt_open(UErrorCode* status);
+
+/**
+ * Cleanup any additional memory allocated by this UFormattable.
+ * @draft ICU 52
+ */
+U_DRAFT void U_EXPORT2
+ufmt_close(UFormattable* fmt);
+
+#if U_SHOW_CPLUSPLUS_API
+
+U_NAMESPACE_BEGIN
+
+/**
+ * \class LocalUFormattablePointer
+ * "Smart pointer" class, closes a UFormattable via ufmt_close().
+ * For most methods see the LocalPointerBase base class.
+ *
+ * @see LocalPointerBase
+ * @see LocalPointer
+ * @draft ICU 52
+ */
+U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattablePointer, UFormattable, ufmt_close);
+
+U_NAMESPACE_END
+
+#endif
+
+/**
+ * Return the type of this object
+ * @param fmt the UFormattable object
+ * @status status code - U_ILLEGAL_ARGUMENT_ERROR is returned if the UFormattable contains data not supported by
+ * the API
+ * @return the value as a UFormattableType
+ * @internal
+ */
+U_INTERNAL UFormattableType U_EXPORT2
+ufmt_getType(UFormattable* fmt, UErrorCode *status);
+
+/**
+ * Return the type of this object
+ * @param fmt the UFormattable object
+ * @return true if the object is a double, long, or int64 value.
+ * @internal
+ */
+U_INTERNAL UBool U_EXPORT2
+ufmt_isNumeric(UFormattable* fmt);
+
+
+/**
+ * Get the value as a date, converting if need be.
+ * @param fmt the UFormattable object
+ * @param status the error code - any conversion or format errors
+ * @return the value
+ * @draft ICU 52
+ */
+U_DRAFT UDate U_EXPORT2
+ufmt_getDate(UFormattable* fmt, UErrorCode *status);
+
+/**
+ * Get the value as a double, converting if need be.
+ * @param fmt the UFormattable object
+ * @param status the error code - any conversion or format errors
+ * @return the value
+ * @draft ICU 52
+ */
+U_DRAFT double U_EXPORT2
+ufmt_getDouble(UFormattable* fmt, UErrorCode *status);
+
+/**
+ * Get the value as a int32_t, converting if need be.
+ * @param fmt the UFormattable object
+ * @param status the error code - any conversion or format errors
+ * @return the value
+ * @draft ICU 52
+ */
+U_DRAFT int32_t U_EXPORT2
+ufmt_getLong(UFormattable* fmt, UErrorCode *status);
+
+
+/**
+ * Get the value as a int64_t, converting if need be.
+ * @param fmt the UFormattable object
+ * @param status the error code - any conversion or format errors
+ * @return the value
+ * @draft ICU 52
+ */
+U_DRAFT int64_t U_EXPORT2
+ufmt_getInt64(UFormattable* fmt, UErrorCode *status);
+
+/**
+ * Get the value as an object.
+ * @param fmt the UFormattable object
+ * @param status the error code - any conversion or format errors
+ * @return the value as a const void*. It is a polymorphic C++ object.
+ * @draft ICU 52
+ */
+U_DRAFT const void *U_EXPORT2
+ufmt_getObject(UFormattable* fmt, UErrorCode *status);
+
+/**
+ * Get the value as UChar string, converting if need be.
+ * This function is not thread safe and may modify the UFormattable if need be to terminate the buffer.
+ * @param fmt the UFormattable object
+ * @param status the error code - any conversion or format errors
+ * @param len if non null, contains the string length on return
+ * @return the null terminated string value - must not be referenced after any other functions are called on this UFormattable.
+ * @draft ICU 52
+ */
+U_DRAFT const UChar* U_EXPORT2
+ufmt_getUChars(UFormattable* fmt, int32_t *len, UErrorCode *status);
+
+/**
+ * Get the number of array objects contained. Invalid if the object is not an array type.
+ * @param fmt the UFormattable object
+ * @param status the error code - any conversion or format errors. U_ILLEGAL_ARGUMENT_ERROR if not an array type.
+ * @return the number of array objects
+ * @draft ICU 52
+ */
+U_DRAFT int32_t U_EXPORT2
+ufmt_getArrayLength(UFormattable* fmt, UErrorCode *status);
+
+/**
+ * Get the specified value from the array of UFormattables. Invalid if the object is not an array type.
+ * @param fmt the UFormattable object
+ * #param n the number of the array to return (0 based).
+ * @param status the error code - any conversion or format errors. Returns an error if n is out of bounds.
+ * @return the nth array value, only valid while the containing UFormattable is valid
+ * @draft ICU 52
+ */
+U_DRAFT UFormattable * U_EXPORT2
+ufmt_getArrayItemByIndex(UFormattable* fmt, int32_t n, UErrorCode *status);
+
+/**
+ * Get the value as a C String, if it is a numeric type (isNumeric is true), or if is an Object
+ * with a numeric value. The returned string is not valid if any other function calls are made on this
+ * object, or if it is destroyed.
+ * @param fmt the UFormattable object
+ * @param len if non-null, on exit contains the string length (not including the terminating null)
+ * @param status the error code
+ * @return the character buffer, which is owned by the object and must not be accessed if any other functions are called on this object.
+ * @draft ICU 52
+ */
+U_DRAFT const char * U_EXPORT2
+ufmt_getDecNumChars(UFormattable *fmt, int32_t *len, UErrorCode *status);
+
+#endif
+
+#endif
return left + buffer;
}
+UnicodeString
+operator+(const UnicodeString& left,
+ int64_t num) {
+ return left + Int64ToUnicodeString(num);
+}
+
#if !UCONFIG_NO_FORMATTING
/**
return UnicodeString() + (long)n;
}
+
+
+UnicodeString toString(UBool b) {
+ return b ? UnicodeString("TRUE"):UnicodeString("false");
+}
+
// stephen - cleaned up 05/05/99
UnicodeString operator+(const UnicodeString& left, char num)
{ return left + (long)num; }
return TRUE;
}
+UBool IntlTest::assertEquals(const char* message,
+ int64_t expected,
+ int64_t actual) {
+ if (expected != actual) {
+ errln((UnicodeString)"FAIL: " + message + "; got " +
+ actual +
+ "; expected " + expected );
+ return FALSE;
+ }
+#ifdef VERBOSE_ASSERTIONS
+ else {
+ logln((UnicodeString)"Ok: " + message + "; got " + actual);
+ }
+#endif
+ return TRUE;
+}
+
+UBool IntlTest::assertEquals(const char* message,
+ UBool expected,
+ UBool actual) {
+ if (expected != actual) {
+ errln((UnicodeString)"FAIL: " + message + "; got " +
+ toString(actual) +
+ "; expected " + toString(expected));
+ return FALSE;
+ }
+#ifdef VERBOSE_ASSERTIONS
+ else {
+ logln((UnicodeString)"Ok: " + message + "; got " + toString(actual));
+ }
+#endif
+ return TRUE;
+}
+
#if !UCONFIG_NO_FORMATTING
UBool IntlTest::assertEquals(const char* message,
const Formattable& expected,
const char* actual) {
return assertEquals(extractToAssertBuf(message), expected, actual);
}
+UBool IntlTest::assertEquals(const UnicodeString& message,
+ UBool expected,
+ UBool actual) {
+ return assertEquals(extractToAssertBuf(message), expected, actual);
+}
+UBool IntlTest::assertEquals(const UnicodeString& message,
+ int32_t expected,
+ int32_t actual) {
+ return assertEquals(extractToAssertBuf(message), expected, actual);
+}
+UBool IntlTest::assertEquals(const UnicodeString& message,
+ int64_t expected,
+ int64_t actual) {
+ return assertEquals(extractToAssertBuf(message), expected, actual);
+}
//--------------------------------------------------------------------
// Time bomb - allows temporary behavior that expires at a given
// release
//string-concatenation operator (moved from findword test by rtg)
UnicodeString UCharToUnicodeString(UChar c);
UnicodeString Int64ToUnicodeString(int64_t num);
-//UnicodeString operator+(const UnicodeString& left, int64_t num); // Some compilers don't allow this because of the long type.
+UnicodeString operator+(const UnicodeString& left, int64_t num);
UnicodeString operator+(const UnicodeString& left, long num);
UnicodeString operator+(const UnicodeString& left, unsigned long num);
UnicodeString operator+(const UnicodeString& left, double num);
-UnicodeString operator+(const UnicodeString& left, char num);
-UnicodeString operator+(const UnicodeString& left, short num);
-UnicodeString operator+(const UnicodeString& left, int num);
-UnicodeString operator+(const UnicodeString& left, unsigned char num);
-UnicodeString operator+(const UnicodeString& left, unsigned short num);
-UnicodeString operator+(const UnicodeString& left, unsigned int num);
+UnicodeString operator+(const UnicodeString& left, char num);
+UnicodeString operator+(const UnicodeString& left, short num);
+UnicodeString operator+(const UnicodeString& left, int num);
+UnicodeString operator+(const UnicodeString& left, unsigned char num);
+UnicodeString operator+(const UnicodeString& left, unsigned short num);
+UnicodeString operator+(const UnicodeString& left, unsigned int num);
UnicodeString operator+(const UnicodeString& left, float num);
#if !UCONFIG_NO_FORMATTING
UnicodeString toString(const Formattable& f); // liu
UnicodeString toString(int32_t n);
#endif
+UnicodeString toString(UBool b);
+
//-----------------------------------------------------------------------------
// Use the TESTCASE macro in subclasses of IntlTest. Define the
void errln(const char *fmt, ...);
void dataerr(const char *fmt, ...);
void dataerrln(const char *fmt, ...);
+
+ /**
+ * logs an error (even if status==U_ZERO_ERROR), but
+ * calls dataerrln() or errln() depending on the type of error.
+ * Does not report the status code.
+ * @param status parameter for selecting whether errln or dataerrln is called.
+ */
void errcheckln(UErrorCode status, const char *fmt, ...);
// Print ALL named errors encountered so far
/* JUnit-like assertions. Each returns TRUE if it succeeds. */
UBool assertTrue(const char* message, UBool condition, UBool quiet=FALSE, UBool possibleDataError=FALSE, const char *file=NULL, int line=0);
UBool assertFalse(const char* message, UBool condition, UBool quiet=FALSE);
+ /**
+ * @param possibleDataError - if TRUE, use dataerrln instead of errcheckln on failure
+ * @return TRUE on success, FALSE on failure.
+ */
UBool assertSuccess(const char* message, UErrorCode ec, UBool possibleDataError=FALSE);
UBool assertEquals(const char* message, const UnicodeString& expected,
const UnicodeString& actual, UBool possibleDataError=FALSE);
UBool assertEquals(const char* message, const char* expected,
const char* actual);
+ UBool assertEquals(const char* message, UBool expected,
+ UBool actual);
UBool assertEquals(const char* message, int32_t expected, int32_t actual);
+ UBool assertEquals(const char* message, int64_t expected, int64_t actual);
#if !UCONFIG_NO_FORMATTING
UBool assertEquals(const char* message, const Formattable& expected,
const Formattable& actual);
const UnicodeString& actual);
UBool assertEquals(const UnicodeString& message, const char* expected,
const char* actual);
+ UBool assertEquals(const UnicodeString& message, UBool expected, UBool actual);
+ UBool assertEquals(const UnicodeString& message, int32_t expected, int32_t actual);
+ UBool assertEquals(const UnicodeString& message, int64_t expected, int64_t actual);
virtual void runIndexedTest( int32_t index, UBool exec, const char* &name, char* par = NULL ); // overide !
TESTCASE_AUTO(Test9087);
TESTCASE_AUTO(TestFormatFastpaths);
TESTCASE_AUTO(TestFormattableSize);
+ TESTCASE_AUTO(TestUFormattable);
TESTCASE_AUTO(TestSignificantDigits);
TESTCASE_AUTO(TestShowZero);
TESTCASE_AUTO(TestCompatibleCurrencies);
}
}
+UBool NumberFormatTest::testFormattableAsUFormattable(const char *file, int line, Formattable &f) {
+ UnicodeString fileLine = UnicodeString(file)+UnicodeString(":")+line+UnicodeString(": ");
+
+ UFormattable *u = f.toUFormattable();
+ logln();
+ if (u == NULL) {
+ errln("%s:%d: Error: f.toUFormattable() retuned NULL.");
+ return FALSE;
+ }
+ logln("%s:%d: comparing Formattable with UFormattable", file, line);
+ logln(fileLine + toString(f));
+
+ UErrorCode status = U_ZERO_ERROR;
+ UErrorCode valueStatus = U_ZERO_ERROR;
+ UFormattableType expectUType = UFMT_COUNT; // invalid
+
+ UBool triedExact = FALSE; // did we attempt an exact comparison?
+ UBool exactMatch = FALSE; // was the exact comparison true?
+
+ switch( f.getType() ) {
+ case Formattable::kDate:
+ expectUType = UFMT_DATE;
+ exactMatch = (f.getDate()==ufmt_getDate(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ case Formattable::kDouble:
+ expectUType = UFMT_DOUBLE;
+ exactMatch = (f.getDouble()==ufmt_getDouble(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ case Formattable::kLong:
+ expectUType = UFMT_LONG;
+ exactMatch = (f.getLong()==ufmt_getLong(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ case Formattable::kString:
+ expectUType = UFMT_STRING;
+ {
+ UnicodeString str;
+ f.getString(str);
+ int32_t len;
+ const UChar* uch = ufmt_getUChars(u, &len, &valueStatus);
+ if(U_SUCCESS(valueStatus)) {
+ UnicodeString str2(uch, len);
+ exactMatch = (str == str2);
+ }
+ triedExact = TRUE;
+ }
+ break;
+ case Formattable::kArray:
+ expectUType = UFMT_ARRAY;
+ triedExact = TRUE;
+ {
+ int32_t count = ufmt_getArrayLength(u, &valueStatus);
+ int32_t count2;
+ const Formattable *array2 = f.getArray(count2);
+ exactMatch = assertEquals(fileLine + " array count", count, count2);
+
+ if(exactMatch) {
+ for(int i=0;U_SUCCESS(valueStatus) && i<count;i++) {
+ UFormattable *uu = ufmt_getArrayItemByIndex(u, i, &valueStatus);
+ if(*Formattable::fromUFormattable(uu) != (array2[i])) {
+ errln("%s:%d: operator== did not match at index[%d] - %p vs %p", file, line, i,
+ (const void*)Formattable::fromUFormattable(uu), (const void*)&(array2[i]));
+ exactMatch = FALSE;
+ } else {
+ if(!testFormattableAsUFormattable("(sub item)",i,*Formattable::fromUFormattable(uu))) {
+ exactMatch = FALSE;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case Formattable::kInt64:
+ expectUType = UFMT_INT64;
+ exactMatch = (f.getInt64()==ufmt_getInt64(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ case Formattable::kObject:
+ expectUType = UFMT_OBJECT;
+ exactMatch = (f.getObject()==ufmt_getObject(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ }
+ UFormattableType uType = ufmt_getType(u, &status);
+
+ if(U_FAILURE(status)) {
+ errln("%s:%d: Error calling ufmt_getType - %s", file, line, u_errorName(status));
+ return FALSE;
+ }
+
+ if(uType != expectUType) {
+ errln("%s:%d: got type (%d) expected (%d) from ufmt_getType", file, line, (int) uType, (int) expectUType);
+ }
+
+ if(triedExact) {
+ if(U_FAILURE(valueStatus)) {
+ errln("%s:%d: got err %s trying to ufmt_get...() for exact match check", file, line, u_errorName(valueStatus));
+ } else if(!exactMatch) {
+ errln("%s:%d: failed exact match for the Formattable type", file, line);
+ } else {
+ logln("%s:%d: exact match OK", file, line);
+ }
+ } else {
+ logln("%s:%d: note, did not attempt exact match for this formattable type", file, line);
+ }
+
+ if( assertEquals(fileLine + " isNumeric()", f.isNumeric(), ufmt_isNumeric(u))
+ && f.isNumeric()) {
+ UErrorCode convStatus = U_ZERO_ERROR;
+ assertTrue(fileLine + " as doubles ==", f.getDouble(convStatus)==ufmt_getDouble(u, &convStatus));
+
+ if( assertSuccess(fileLine + " (numeric conversion status)", convStatus) ) {
+ StringPiece fDecNum = f.getDecimalNumber(convStatus);
+#if 1
+ int32_t len;
+ const char *decNumChars = ufmt_getDecNumChars(u, &len, &convStatus);
+#else
+ // copy version
+ char decNumChars[200];
+ int32_t len = ufmt_getDecNumChars(u, decNumChars, 200, &convStatus);
+#endif
+
+ if( assertSuccess(fileLine + " (decNumbers conversion)", convStatus) ) {
+ logln(fileLine + decNumChars);
+ assertEquals(fileLine + " decNumChars length==", len, fDecNum.length());
+ assertEquals(fileLine + " decNumChars digits", decNumChars, fDecNum.data());
+ }
+
+ UErrorCode int64ConversionF = U_ZERO_ERROR;
+ int64_t l = f.getInt64(int64ConversionF);
+ UErrorCode int64ConversionU = U_ZERO_ERROR;
+ int64_t r = ufmt_getInt64(u, &int64ConversionU);
+
+ if( (l==r)
+ && ( uType != UFMT_INT64 ) // int64 better not overflow
+ && (U_INVALID_FORMAT_ERROR==int64ConversionU)
+ && (U_INVALID_FORMAT_ERROR==int64ConversionF) ) {
+ logln("%s:%d: OK: 64 bit overflow", file, line);
+ } else {
+ assertEquals(fileLine + " as int64 ==", l, r);
+ assertSuccess(fileLine + " Formattable.getnt64()", int64ConversionF);
+ assertSuccess(fileLine + " ufmt_getInt64()", int64ConversionU);
+ }
+ }
+ }
+ return exactMatch || !triedExact;
+}
+
+void NumberFormatTest::TestUFormattable(void) {
+ {
+ // test that a default formattable is equal to Formattable()
+ UErrorCode status = U_ZERO_ERROR;
+ LocalUFormattablePointer defaultUFormattable(ufmt_open(&status));
+ assertSuccess("calling umt_open", status);
+ Formattable defaultFormattable;
+ assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
+ (defaultFormattable
+ == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
+ assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
+ (defaultFormattable
+ == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
+ assertTrue((UnicodeString)"comparing Formattable() round tripped through UFormattable",
+ (defaultFormattable
+ == *(Formattable::fromUFormattable(defaultFormattable.toUFormattable()))));
+ assertTrue((UnicodeString)"comparing &Formattable() round tripped through UFormattable",
+ ((&defaultFormattable)
+ == Formattable::fromUFormattable(defaultFormattable.toUFormattable())));
+ assertFalse((UnicodeString)"comparing &Formattable() with ufmt_open()",
+ ((&defaultFormattable)
+ == Formattable::fromUFormattable(defaultUFormattable.getAlias())));
+ testFormattableAsUFormattable(__FILE__, __LINE__, defaultFormattable);
+ }
+ // test some random Formattables
+ {
+ Formattable f(ucal_getNow(), Formattable::kIsDate);
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ Formattable f((double)1.61803398874989484820); // golden ratio
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ Formattable f((int64_t)80994231587905127LL); // weight of the moon, in kilotons http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ Formattable f((int32_t)4); // random number, source: http://www.xkcd.com/221/
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ Formattable f("Hello world."); // should be invariant?
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ UErrorCode status2 = U_ZERO_ERROR;
+ Formattable f(StringPiece("73476730924573500000000.0"), status2); // weight of the moon, kg
+ assertSuccess("Constructing a StringPiece", status2);
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ UErrorCode status2 = U_ZERO_ERROR;
+ UObject *obj = new Locale();
+ Formattable f(obj);
+ assertSuccess("Constructing a Formattable from a default constructed Locale()", status2);
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ const Formattable array[] = {
+ Formattable(ucal_getNow(), Formattable::kIsDate),
+ Formattable((int32_t)4),
+ Formattable((double)1.234),
+ };
+
+ Formattable fa(array, 3);
+ testFormattableAsUFormattable(__FILE__, __LINE__, fa);
+ }
+}
+
void NumberFormatTest::TestSignificantDigits(void) {
double input[] = {
0, 0,
void TestFormattableSize();
+ void TestUFormattable();
+
void TestEnumSet();
void TestSignificantDigits();
void TestBug9936();
private:
+ UBool testFormattableAsUFormattable(const char *file, int line, Formattable &f);
+
void expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text);
static UBool equalValue(const Formattable& a, const Formattable& b);