1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042 |
- // © 2016 and later: Unicode, Inc. and others.
- // License & terms of use: http://www.unicode.org/copyright.html
- /*
- *******************************************************************************
- * Copyright (C) 1997-2016, International Business Machines Corporation and
- * others. All Rights Reserved.
- *******************************************************************************
- *
- * File FMTABLE.CPP
- *
- * Modification History:
- *
- * Date Name Description
- * 03/25/97 clhuang Initial Implementation.
- ********************************************************************************
- */
- #include "unicode/utypes.h"
- #if !UCONFIG_NO_FORMATTING
- #include <cstdlib>
- #include <math.h>
- #include "unicode/fmtable.h"
- #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"
- #include "fmtableimp.h"
- #include "number_decimalquantity.h"
- // *****************************************************************************
- // class Formattable
- // *****************************************************************************
- U_NAMESPACE_BEGIN
- UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)
- using number::impl::DecimalQuantity;
- //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
- // NOTE: As of 3.0, there are limitations to the UObject API. It does
- // not (yet) support cloning, operator=, nor operator==. To
- // work around this, I implement some simple inlines here. Later
- // these can be modified or removed. [alan]
- // NOTE: These inlines assume that all fObjects are in fact instances
- // of the Measure class, which is true as of 3.0. [alan]
- // Return true if *a == *b.
- static inline UBool objectEquals(const UObject* a, const UObject* b) {
- // LATER: return *a == *b;
- return *((const Measure*) a) == *((const Measure*) b);
- }
- // Return a clone of *a.
- static inline UObject* objectClone(const UObject* a) {
- // LATER: return a->clone();
- return ((const Measure*) a)->clone();
- }
- // Return true if *a is an instance of Measure.
- static inline UBool instanceOfMeasure(const UObject* a) {
- return dynamic_cast<const Measure*>(a) != nullptr;
- }
- /**
- * Creates a new Formattable array and copies the values from the specified
- * original.
- * @param array the original array
- * @param count the original array count
- * @return the new Formattable array.
- */
- static Formattable* createArrayCopy(const Formattable* array, int32_t count) {
- Formattable *result = new Formattable[count];
- if (result != nullptr) {
- for (int32_t i=0; i<count; ++i)
- result[i] = array[i]; // Don't memcpy!
- }
- return result;
- }
- //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
- /**
- * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
- */
- static void setError(UErrorCode& ec, UErrorCode err) {
- if (U_SUCCESS(ec)) {
- ec = err;
- }
- }
- //
- // Common initialization code, shared by constructors.
- // Put everything into a known state.
- //
- void Formattable::init() {
- fValue.fInt64 = 0;
- fType = kLong;
- fDecimalStr = nullptr;
- fDecimalQuantity = nullptr;
- fBogus.setToBogus();
- }
- // -------------------------------------
- // default constructor.
- // Creates a formattable object with a long value 0.
- Formattable::Formattable() {
- init();
- }
- // -------------------------------------
- // Creates a formattable object with a Date instance.
- Formattable::Formattable(UDate date, ISDATE /*isDate*/)
- {
- init();
- fType = kDate;
- fValue.fDate = date;
- }
- // -------------------------------------
- // Creates a formattable object with a double value.
- Formattable::Formattable(double value)
- {
- init();
- fType = kDouble;
- fValue.fDouble = value;
- }
- // -------------------------------------
- // Creates a formattable object with an int32_t value.
- Formattable::Formattable(int32_t value)
- {
- init();
- fValue.fInt64 = value;
- }
- // -------------------------------------
- // Creates a formattable object with an int64_t value.
- Formattable::Formattable(int64_t value)
- {
- init();
- fType = kInt64;
- fValue.fInt64 = value;
- }
- // -------------------------------------
- // Creates a formattable object with a decimal number value from a string.
- Formattable::Formattable(StringPiece number, UErrorCode &status) {
- init();
- setDecimalNumber(number, status);
- }
- // -------------------------------------
- // Creates a formattable object with a UnicodeString instance.
- Formattable::Formattable(const UnicodeString& stringToCopy)
- {
- init();
- fType = kString;
- fValue.fString = new UnicodeString(stringToCopy);
- }
- // -------------------------------------
- // Creates a formattable object with a UnicodeString* value.
- // (adopting semantics)
- Formattable::Formattable(UnicodeString* stringToAdopt)
- {
- init();
- fType = kString;
- fValue.fString = stringToAdopt;
- }
- Formattable::Formattable(UObject* objectToAdopt)
- {
- init();
- fType = kObject;
- fValue.fObject = objectToAdopt;
- }
- // -------------------------------------
- Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
- : UObject(), fType(kArray)
- {
- init();
- fType = kArray;
- fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count);
- fValue.fArrayAndCount.fCount = count;
- }
- // -------------------------------------
- // copy constructor
- Formattable::Formattable(const Formattable &source)
- : UObject(*this)
- {
- init();
- *this = source;
- }
- // -------------------------------------
- // assignment operator
- Formattable&
- Formattable::operator=(const Formattable& source)
- {
- if (this != &source)
- {
- // Disposes the current formattable value/setting.
- dispose();
- // Sets the correct data type for this value.
- fType = source.fType;
- switch (fType)
- {
- case kArray:
- // Sets each element in the array one by one and records the array count.
- fValue.fArrayAndCount.fCount = source.fValue.fArrayAndCount.fCount;
- fValue.fArrayAndCount.fArray = createArrayCopy(source.fValue.fArrayAndCount.fArray,
- source.fValue.fArrayAndCount.fCount);
- break;
- case kString:
- // Sets the string value.
- fValue.fString = new UnicodeString(*source.fValue.fString);
- break;
- case kDouble:
- // Sets the double value.
- fValue.fDouble = source.fValue.fDouble;
- break;
- case kLong:
- case kInt64:
- // Sets the long value.
- fValue.fInt64 = source.fValue.fInt64;
- break;
- case kDate:
- // Sets the Date value.
- fValue.fDate = source.fValue.fDate;
- break;
- case kObject:
- fValue.fObject = objectClone(source.fValue.fObject);
- break;
- }
- UErrorCode status = U_ZERO_ERROR;
- if (source.fDecimalQuantity != nullptr) {
- fDecimalQuantity = new DecimalQuantity(*source.fDecimalQuantity);
- }
- if (source.fDecimalStr != nullptr) {
- fDecimalStr = new CharString(*source.fDecimalStr, status);
- if (U_FAILURE(status)) {
- delete fDecimalStr;
- fDecimalStr = nullptr;
- }
- }
- }
- return *this;
- }
- // -------------------------------------
- bool
- Formattable::operator==(const Formattable& that) const
- {
- int32_t i;
- if (this == &that) return true;
- // Returns false if the data types are different.
- if (fType != that.fType) return false;
- // Compares the actual data values.
- bool equal = true;
- switch (fType) {
- case kDate:
- equal = (fValue.fDate == that.fValue.fDate);
- break;
- case kDouble:
- equal = (fValue.fDouble == that.fValue.fDouble);
- break;
- case kLong:
- case kInt64:
- equal = (fValue.fInt64 == that.fValue.fInt64);
- break;
- case kString:
- equal = (*(fValue.fString) == *(that.fValue.fString));
- break;
- case kArray:
- if (fValue.fArrayAndCount.fCount != that.fValue.fArrayAndCount.fCount) {
- equal = false;
- break;
- }
- // Checks each element for equality.
- for (i=0; i<fValue.fArrayAndCount.fCount; ++i) {
- if (fValue.fArrayAndCount.fArray[i] != that.fValue.fArrayAndCount.fArray[i]) {
- equal = false;
- break;
- }
- }
- break;
- case kObject:
- if (fValue.fObject == nullptr || that.fValue.fObject == nullptr) {
- equal = false;
- } else {
- equal = objectEquals(fValue.fObject, that.fValue.fObject);
- }
- break;
- }
- // TODO: compare digit lists if numeric.
- return equal;
- }
- // -------------------------------------
- Formattable::~Formattable()
- {
- dispose();
- }
- // -------------------------------------
- void Formattable::dispose()
- {
- // Deletes the data value if necessary.
- switch (fType) {
- case kString:
- delete fValue.fString;
- break;
- case kArray:
- delete[] fValue.fArrayAndCount.fArray;
- break;
- case kObject:
- delete fValue.fObject;
- break;
- default:
- break;
- }
- fType = kLong;
- fValue.fInt64 = 0;
- delete fDecimalStr;
- fDecimalStr = nullptr;
- delete fDecimalQuantity;
- fDecimalQuantity = nullptr;
- }
- Formattable *
- Formattable::clone() const {
- return new Formattable(*this);
- }
- // -------------------------------------
- // Gets the data type of this Formattable object.
- Formattable::Type
- Formattable::getType() const
- {
- return fType;
- }
- UBool
- Formattable::isNumeric() const {
- switch (fType) {
- case kDouble:
- case kLong:
- case kInt64:
- return true;
- default:
- return false;
- }
- }
- // -------------------------------------
- int32_t
- //Formattable::getLong(UErrorCode* status) const
- Formattable::getLong(UErrorCode& status) const
- {
- if (U_FAILURE(status)) {
- return 0;
- }
-
- switch (fType) {
- case Formattable::kLong:
- return (int32_t)fValue.fInt64;
- case Formattable::kInt64:
- if (fValue.fInt64 > INT32_MAX) {
- status = U_INVALID_FORMAT_ERROR;
- return INT32_MAX;
- } else if (fValue.fInt64 < INT32_MIN) {
- status = U_INVALID_FORMAT_ERROR;
- return INT32_MIN;
- } else {
- return (int32_t)fValue.fInt64;
- }
- case Formattable::kDouble:
- if (fValue.fDouble > INT32_MAX) {
- status = U_INVALID_FORMAT_ERROR;
- return INT32_MAX;
- } else if (fValue.fDouble < INT32_MIN) {
- status = U_INVALID_FORMAT_ERROR;
- return INT32_MIN;
- } else {
- return (int32_t)fValue.fDouble; // loses fraction
- }
- case Formattable::kObject:
- if (fValue.fObject == nullptr) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return 0;
- }
- // TODO Later replace this with instanceof call
- if (instanceOfMeasure(fValue.fObject)) {
- return ((const Measure*) fValue.fObject)->
- getNumber().getLong(status);
- }
- U_FALLTHROUGH;
- default:
- status = U_INVALID_FORMAT_ERROR;
- return 0;
- }
- }
- // -------------------------------------
- // Maximum int that can be represented exactly in a double. (53 bits)
- // Larger ints may be rounded to a near-by value as not all are representable.
- // TODO: move this constant elsewhere, possibly configure it for different
- // floating point formats, if any non-standard ones are still in use.
- static const int64_t U_DOUBLE_MAX_EXACT_INT = 9007199254740992LL;
- int64_t
- Formattable::getInt64(UErrorCode& status) const
- {
- if (U_FAILURE(status)) {
- return 0;
- }
-
- switch (fType) {
- case Formattable::kLong:
- case Formattable::kInt64:
- return fValue.fInt64;
- case Formattable::kDouble:
- if (fValue.fDouble > (double)U_INT64_MAX) {
- status = U_INVALID_FORMAT_ERROR;
- return U_INT64_MAX;
- } else if (fValue.fDouble < (double)U_INT64_MIN) {
- status = U_INVALID_FORMAT_ERROR;
- return U_INT64_MIN;
- } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalQuantity != nullptr) {
- if (fDecimalQuantity->fitsInLong(true)) {
- return fDecimalQuantity->toLong();
- } else {
- // Unexpected
- status = U_INVALID_FORMAT_ERROR;
- return fDecimalQuantity->isNegative() ? U_INT64_MIN : U_INT64_MAX;
- }
- } else {
- return (int64_t)fValue.fDouble;
- }
- case Formattable::kObject:
- if (fValue.fObject == nullptr) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return 0;
- }
- if (instanceOfMeasure(fValue.fObject)) {
- return ((const Measure*) fValue.fObject)->
- getNumber().getInt64(status);
- }
- U_FALLTHROUGH;
- default:
- status = U_INVALID_FORMAT_ERROR;
- return 0;
- }
- }
- // -------------------------------------
- double
- Formattable::getDouble(UErrorCode& status) const
- {
- if (U_FAILURE(status)) {
- return 0;
- }
-
- switch (fType) {
- case Formattable::kLong:
- case Formattable::kInt64: // loses precision
- return (double)fValue.fInt64;
- case Formattable::kDouble:
- return fValue.fDouble;
- case Formattable::kObject:
- if (fValue.fObject == nullptr) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return 0;
- }
- // TODO Later replace this with instanceof call
- if (instanceOfMeasure(fValue.fObject)) {
- return ((const Measure*) fValue.fObject)->
- getNumber().getDouble(status);
- }
- U_FALLTHROUGH;
- default:
- status = U_INVALID_FORMAT_ERROR;
- return 0;
- }
- }
- const UObject*
- Formattable::getObject() const {
- return (fType == kObject) ? fValue.fObject : nullptr;
- }
- // -------------------------------------
- // Sets the value to a double value d.
- void
- Formattable::setDouble(double d)
- {
- dispose();
- fType = kDouble;
- fValue.fDouble = d;
- }
- // -------------------------------------
- // Sets the value to a long value l.
- void
- Formattable::setLong(int32_t l)
- {
- dispose();
- fType = kLong;
- fValue.fInt64 = l;
- }
- // -------------------------------------
- // Sets the value to an int64 value ll.
- void
- Formattable::setInt64(int64_t ll)
- {
- dispose();
- fType = kInt64;
- fValue.fInt64 = ll;
- }
- // -------------------------------------
- // Sets the value to a Date instance d.
- void
- Formattable::setDate(UDate d)
- {
- dispose();
- fType = kDate;
- fValue.fDate = d;
- }
- // -------------------------------------
- // Sets the value to a string value stringToCopy.
- void
- Formattable::setString(const UnicodeString& stringToCopy)
- {
- dispose();
- fType = kString;
- fValue.fString = new UnicodeString(stringToCopy);
- }
- // -------------------------------------
- // Sets the value to an array of Formattable objects.
- void
- Formattable::setArray(const Formattable* array, int32_t count)
- {
- dispose();
- fType = kArray;
- fValue.fArrayAndCount.fArray = createArrayCopy(array, count);
- fValue.fArrayAndCount.fCount = count;
- }
- // -------------------------------------
- // Adopts the stringToAdopt value.
- void
- Formattable::adoptString(UnicodeString* stringToAdopt)
- {
- dispose();
- fType = kString;
- fValue.fString = stringToAdopt;
- }
- // -------------------------------------
- // Adopts the array value and its count.
- void
- Formattable::adoptArray(Formattable* array, int32_t count)
- {
- dispose();
- fType = kArray;
- fValue.fArrayAndCount.fArray = array;
- fValue.fArrayAndCount.fCount = count;
- }
- void
- Formattable::adoptObject(UObject* objectToAdopt) {
- dispose();
- fType = kObject;
- fValue.fObject = objectToAdopt;
- }
- // -------------------------------------
- UnicodeString&
- Formattable::getString(UnicodeString& result, UErrorCode& status) const
- {
- if (fType != kString) {
- setError(status, U_INVALID_FORMAT_ERROR);
- result.setToBogus();
- } else {
- if (fValue.fString == nullptr) {
- setError(status, U_MEMORY_ALLOCATION_ERROR);
- } else {
- result = *fValue.fString;
- }
- }
- return result;
- }
- // -------------------------------------
- const UnicodeString&
- Formattable::getString(UErrorCode& status) const
- {
- if (fType != kString) {
- setError(status, U_INVALID_FORMAT_ERROR);
- return *getBogus();
- }
- if (fValue.fString == nullptr) {
- setError(status, U_MEMORY_ALLOCATION_ERROR);
- return *getBogus();
- }
- return *fValue.fString;
- }
- // -------------------------------------
- UnicodeString&
- Formattable::getString(UErrorCode& status)
- {
- if (fType != kString) {
- setError(status, U_INVALID_FORMAT_ERROR);
- return *getBogus();
- }
- if (fValue.fString == nullptr) {
- setError(status, U_MEMORY_ALLOCATION_ERROR);
- return *getBogus();
- }
- return *fValue.fString;
- }
- // -------------------------------------
- const Formattable*
- Formattable::getArray(int32_t& count, UErrorCode& status) const
- {
- if (fType != kArray) {
- setError(status, U_INVALID_FORMAT_ERROR);
- count = 0;
- return nullptr;
- }
- count = fValue.fArrayAndCount.fCount;
- return fValue.fArrayAndCount.fArray;
- }
- // -------------------------------------
- // Gets the bogus string, ensures mondo bogosity.
- UnicodeString*
- Formattable::getBogus() const
- {
- return (UnicodeString*)&fBogus; /* cast away const :-( */
- }
- // --------------------------------------
- StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
- if (U_FAILURE(status)) {
- return "";
- }
- if (fDecimalStr != nullptr) {
- return fDecimalStr->toStringPiece();
- }
- CharString *decimalStr = internalGetCharString(status);
- if(decimalStr == nullptr) {
- return ""; // getDecimalNumber returns "" for error cases
- } else {
- return decimalStr->toStringPiece();
- }
- }
- CharString *Formattable::internalGetCharString(UErrorCode &status) {
- if(fDecimalStr == nullptr) {
- if (fDecimalQuantity == nullptr) {
- // 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.
- //
- LocalPointer<DecimalQuantity> dq(new DecimalQuantity(), status);
- if (U_FAILURE(status)) { return nullptr; }
- populateDecimalQuantity(*dq, status);
- if (U_FAILURE(status)) { return nullptr; }
- fDecimalQuantity = dq.orphan();
- }
- fDecimalStr = new CharString();
- if (fDecimalStr == nullptr) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return nullptr;
- }
- // Older ICUs called uprv_decNumberToString here, which is not exactly the same as
- // DecimalQuantity::toScientificString(). The biggest difference is that uprv_decNumberToString does
- // not print scientific notation for magnitudes greater than -5 and smaller than some amount (+5?).
- if (fDecimalQuantity->isInfinite()) {
- fDecimalStr->append("Infinity", status);
- } else if (fDecimalQuantity->isNaN()) {
- fDecimalStr->append("NaN", status);
- } else if (fDecimalQuantity->isZeroish()) {
- fDecimalStr->append("0", -1, status);
- } else if (fType==kLong || fType==kInt64 || // use toPlainString for integer types
- (fDecimalQuantity->getMagnitude() != INT32_MIN && std::abs(fDecimalQuantity->getMagnitude()) < 5)) {
- fDecimalStr->appendInvariantChars(fDecimalQuantity->toPlainString(), status);
- } else {
- fDecimalStr->appendInvariantChars(fDecimalQuantity->toScientificString(), status);
- }
- }
- return fDecimalStr;
- }
- void
- Formattable::populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const {
- if (fDecimalQuantity != nullptr) {
- output = *fDecimalQuantity;
- return;
- }
- switch (fType) {
- case kDouble:
- output.setToDouble(this->getDouble());
- output.roundToInfinity();
- break;
- case kLong:
- output.setToInt(this->getLong());
- break;
- case kInt64:
- output.setToLong(this->getInt64());
- break;
- default:
- // The formattable's value is not a numeric type.
- status = U_INVALID_STATE_ERROR;
- }
- }
- // ---------------------------------------
- void
- Formattable::adoptDecimalQuantity(DecimalQuantity *dq) {
- if (fDecimalQuantity != nullptr) {
- delete fDecimalQuantity;
- }
- fDecimalQuantity = dq;
- if (dq == nullptr) { // allow adoptDigitList(nullptr) to clear
- return;
- }
- // Set the value into the Union of simple type values.
- // Cannot use the set() functions because they would delete the fDecimalNum value.
- if (fDecimalQuantity->fitsInLong()) {
- fValue.fInt64 = fDecimalQuantity->toLong();
- if (fValue.fInt64 <= INT32_MAX && fValue.fInt64 >= INT32_MIN) {
- fType = kLong;
- } else {
- fType = kInt64;
- }
- } else {
- fType = kDouble;
- fValue.fDouble = fDecimalQuantity->toDouble();
- }
- }
- // ---------------------------------------
- void
- Formattable::setDecimalNumber(StringPiece numberString, UErrorCode &status) {
- if (U_FAILURE(status)) {
- return;
- }
- dispose();
- auto* dq = new DecimalQuantity();
- dq->setToDecNumber(numberString, status);
- adoptDecimalQuantity(dq);
- // Note that we do not hang on to the caller's input string.
- // If we are asked for the string, we will regenerate one from fDecimalQuantity.
- }
- #if 0
- //----------------------------------------------------
- // console I/O
- //----------------------------------------------------
- #ifdef _DEBUG
- #include <iostream>
- using namespace std;
- #include "unicode/datefmt.h"
- #include "unistrm.h"
- class FormattableStreamer /* not : public UObject because all methods are static */ {
- public:
- static void streamOut(ostream& stream, const Formattable& obj);
- private:
- FormattableStreamer() {} // private - forbid instantiation
- };
- // This is for debugging purposes only. This will send a displayable
- // form of the Formattable object to the output stream.
- void
- FormattableStreamer::streamOut(ostream& stream, const Formattable& obj)
- {
- static DateFormat *defDateFormat = 0;
- UnicodeString buffer;
- switch(obj.getType()) {
- case Formattable::kDate :
- // Creates a DateFormat instance for formatting the
- // Date instance.
- if (defDateFormat == 0) {
- defDateFormat = DateFormat::createInstance();
- }
- defDateFormat->format(obj.getDate(), buffer);
- stream << buffer;
- break;
- case Formattable::kDouble :
- // Output the double as is.
- stream << obj.getDouble() << 'D';
- break;
- case Formattable::kLong :
- // Output the double as is.
- stream << obj.getLong() << 'L';
- break;
- case Formattable::kString:
- // Output the double as is. Please see UnicodeString console
- // I/O routine for more details.
- stream << '"' << obj.getString(buffer) << '"';
- break;
- case Formattable::kArray:
- int32_t i, count;
- const Formattable* array;
- array = obj.getArray(count);
- stream << '[';
- // Recursively calling the console I/O routine for each element in the array.
- for (i=0; i<count; ++i) {
- FormattableStreamer::streamOut(stream, array[i]);
- stream << ( (i==(count-1)) ? "" : ", " );
- }
- stream << ']';
- break;
- default:
- // Not a recognizable Formattable object.
- stream << "INVALID_Formattable";
- }
- stream.flush();
- }
- #endif
- #endif
- U_NAMESPACE_END
- /* ---- UFormattable implementation ---- */
- U_NAMESPACE_USE
- U_CAPI UFormattable* U_EXPORT2
- ufmt_open(UErrorCode *status) {
- if( U_FAILURE(*status) ) {
- return nullptr;
- }
- UFormattable *fmt = (new Formattable())->toUFormattable();
- if( fmt == nullptr ) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- }
- return fmt;
- }
- U_CAPI void U_EXPORT2
- ufmt_close(UFormattable *fmt) {
- Formattable *obj = Formattable::fromUFormattable(fmt);
- delete obj;
- }
- U_CAPI UFormattableType U_EXPORT2
- ufmt_getType(const UFormattable *fmt, UErrorCode *status) {
- if(U_FAILURE(*status)) {
- return (UFormattableType)UFMT_COUNT;
- }
- const Formattable *obj = Formattable::fromUFormattable(fmt);
- return (UFormattableType)obj->getType();
- }
- U_CAPI UBool U_EXPORT2
- ufmt_isNumeric(const UFormattable *fmt) {
- const Formattable *obj = Formattable::fromUFormattable(fmt);
- return obj->isNumeric();
- }
- U_CAPI UDate U_EXPORT2
- ufmt_getDate(const UFormattable *fmt, UErrorCode *status) {
- const Formattable *obj = Formattable::fromUFormattable(fmt);
- return obj->getDate(*status);
- }
- U_CAPI double U_EXPORT2
- ufmt_getDouble(UFormattable *fmt, UErrorCode *status) {
- Formattable *obj = Formattable::fromUFormattable(fmt);
- return obj->getDouble(*status);
- }
- U_CAPI int32_t U_EXPORT2
- ufmt_getLong(UFormattable *fmt, UErrorCode *status) {
- Formattable *obj = Formattable::fromUFormattable(fmt);
- return obj->getLong(*status);
- }
- U_CAPI const void *U_EXPORT2
- ufmt_getObject(const UFormattable *fmt, UErrorCode *status) {
- const Formattable *obj = Formattable::fromUFormattable(fmt);
- const void *ret = obj->getObject();
- if( ret==nullptr &&
- (obj->getType() != Formattable::kObject) &&
- U_SUCCESS( *status )) {
- *status = U_INVALID_FORMAT_ERROR;
- }
- return ret;
- }
- U_CAPI const char16_t* 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 nullptr;
- }
- // This should return a valid string
- UnicodeString &str = obj->getString(*status);
- if( U_SUCCESS(*status) && len != nullptr ) {
- *len = str.length();
- }
- return str.getTerminatedBuffer();
- }
- U_CAPI int32_t U_EXPORT2
- ufmt_getArrayLength(const UFormattable* fmt, UErrorCode *status) {
- const Formattable *obj = Formattable::fromUFormattable(fmt);
- int32_t count;
- (void)obj->getArray(count, *status);
- return count;
- }
- U_CAPI 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 nullptr;
- } else if(n<0 || n>=count) {
- setError(*status, U_INDEX_OUTOFBOUNDS_ERROR);
- return nullptr;
- } else {
- return (*obj)[n].toUFormattable(); // returns non-const Formattable
- }
- }
- U_CAPI 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 == nullptr) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return "";
- } else {
- if(len!=nullptr) {
- *len = charString->length();
- }
- return charString->data();
- }
- }
- U_CAPI int64_t U_EXPORT2
- ufmt_getInt64(UFormattable *fmt, UErrorCode *status) {
- Formattable *obj = Formattable::fromUFormattable(fmt);
- return obj->getInt64(*status);
- }
- #endif /* #if !UCONFIG_NO_FORMATTING */
- //eof
|