#include "uvectr32.h"
#include "number_stringbuilder.h"
+
+/**
+ * Represents the type of constraint for ConstrainedFieldPosition.
+ *
+ * Constraints are used to control the behavior of iteration in FormattedValue.
+ *
+ * @internal
+ */
+typedef enum UCFPosConstraintType {
+ /**
+ * Represents the lack of a constraint.
+ *
+ * This is the value of fConstraint if no "constrain" methods were called.
+ *
+ * @internal
+ */
+ UCFPOS_CONSTRAINT_NONE = 0,
+
+ /**
+ * Represents that the field category is constrained.
+ *
+ * This is the value of fConstraint if constraintCategory was called.
+ *
+ * FormattedValue implementations should not change the field category
+ * while this constraint is active.
+ *
+ * @internal
+ */
+ UCFPOS_CONSTRAINT_CATEGORY,
+
+ /**
+ * Represents that the field and field category are constrained.
+ *
+ * This is the value of fConstraint if constraintField was called.
+ *
+ * FormattedValue implementations should not change the field or field category
+ * while this constraint is active.
+ *
+ * @internal
+ */
+ UCFPOS_CONSTRAINT_FIELD
+} UCFPosConstraintType;
+
+
U_NAMESPACE_BEGIN
fContext = context;
}
-void ConstrainedFieldPosition::setState(
- int32_t category,
- int32_t field,
- int32_t start,
- int32_t limit) {
- fCategory = category;
- fField = field;
- fStart = start;
- fLimit = limit;
-}
-
-UBool ConstrainedFieldPosition::matchesField(int32_t category, int32_t field) {
+UBool ConstrainedFieldPosition::matchesField(int32_t category, int32_t field) const {
switch (fConstraint) {
case UCFPOS_CONSTRAINT_NONE:
return TRUE;
}
}
+void ConstrainedFieldPosition::setState(
+ int32_t category,
+ int32_t field,
+ int32_t start,
+ int32_t limit) {
+ fCategory = category;
+ fField = field;
+ fStart = start;
+ fLimit = limit;
+}
+
FormattedValue::~FormattedValue() = default;
impl->fImpl.constrainField(category, field);
}
-U_CAPI UCFPosConstraintType U_EXPORT2
-ucfpos_getConstraintType(const UConstrainedFieldPosition* ptr, UErrorCode* ec) {
- const auto* impl = UConstrainedFieldPositionImpl::validate(ptr, *ec);
- if (U_FAILURE(*ec)) {
- return UCFPOS_CONSTRAINT_NONE;
- }
- return impl->fImpl.getConstraintType();
-}
-
U_CAPI int32_t U_EXPORT2
ucfpos_getCategory(const UConstrainedFieldPosition* ptr, UErrorCode* ec) {
const auto* impl = UConstrainedFieldPositionImpl::validate(ptr, *ec);
impl->fImpl.setInt64IterationContext(context);
}
+U_CAPI UBool U_EXPORT2
+ucfpos_matchesField(const UConstrainedFieldPosition* ptr, int32_t category, int32_t field, UErrorCode* ec) {
+ const auto* impl = UConstrainedFieldPositionImpl::validate(ptr, *ec);
+ if (U_FAILURE(*ec)) {
+ return 0;
+ }
+ return impl->fImpl.matchesField(category, field);
+}
+
U_CAPI void U_EXPORT2
ucfpos_setState(
UConstrainedFieldPosition* ptr,
*/
void constrainField(int32_t category, int32_t field);
- /**
- * Gets the currently active constraint.
- *
- * @return The currently active constraint type.
- * @draft ICU 64
- */
- inline UCFPosConstraintType getConstraintType() const {
- return fConstraint;
- }
-
/**
* Gets the field category for the current position.
*
- * If a category or field constraint was set, this function returns the constrained
- * category. Otherwise, the return value is well-defined only after
+ * The return value is well-defined only after
* FormattedValue#nextPosition returns TRUE.
*
* @return The field category saved in the instance.
/**
* Gets the field for the current position.
*
- * If a field constraint was set, this function returns the constrained
- * field. Otherwise, the return value is well-defined only after
+ * The return value is well-defined only after
* FormattedValue#nextPosition returns TRUE.
*
* @return The field saved in the instance.
*/
void setInt64IterationContext(int64_t context);
+ /**
+ * Determines whether a given field should be included given the
+ * constraints.
+ *
+ * Intended to be used by FormattedValue implementations.
+ *
+ * @param category The category to test.
+ * @param field The field to test.
+ * @draft ICU 64
+ */
+ UBool matchesField(int32_t category, int32_t field) const;
+
/**
* Sets new values for the primary public getters.
*
int32_t start,
int32_t limit);
- /** @internal */
- UBool matchesField(int32_t category, int32_t field);
-
private:
int64_t fContext = 0LL;
int32_t fField = 0;
int32_t fStart = 0;
int32_t fLimit = 0;
- UCFPosConstraintType fConstraint = UCFPOS_CONSTRAINT_NONE;
int32_t fCategory = UFIELD_CATEGORY_UNDEFINED;
+ int8_t fConstraint = 0;
};
} UFieldCategory;
-/**
- * Represents the type of constraint for ConstrainedFieldPosition.
- *
- * Constraints are used to control the behavior of iteration in FormattedValue.
- *
- * @draft ICU 64
- */
-typedef enum UCFPosConstraintType {
- /**
- * Represents the lack of a constraint.
- *
- * This is the return value of ConstrainedFieldPosition#getConstraintType or
- * ucfpos_getConstraintType if no "constrain" methods were called.
- *
- * @draft ICU 64
- */
- UCFPOS_CONSTRAINT_NONE,
-
- /**
- * Represents that the field category is constrained.
- *
- * This is the return value of ConstrainedFieldPosition#getConstraintType or
- * cfpos_getConstraintType after ConstrainedFieldPosition#constrainCategory or
- * cfpos_constrainCategory is called.
- *
- * Use getCategory to access the category. FormattedValue implementations
- * should not change that values while this constraint is active.
- *
- * @draft ICU 64
- */
- UCFPOS_CONSTRAINT_CATEGORY,
-
- /**
- * Represents that the field and field category are constrained.
- *
- * This is the return value of ConstrainedFieldPosition#getConstraintType or
- * cfpos_getConstraintType after ConstrainedFieldPosition#constrainField or
- * cfpos_constrainField is called.
- *
- * Use getCategory and getField to access the category and field.
- * FormattedValue implementations should not change those values while
- * this constraint is active.
- *
- * @draft ICU 64
- */
- UCFPOS_CONSTRAINT_FIELD
-} UCFPosConstraintType;
-
-
struct UConstrainedFieldPosition;
/**
* Represents a span of a string containing a given field.
UErrorCode* ec);
-/**
- * Gets the currently active constraint.
- *
- * @param ucfpos The instance of UConstrainedFieldPosition.
- * @param ec Set if an error occurs.
- * @return The currently active constraint type.
- * @draft ICU 64
- */
-U_DRAFT UCFPosConstraintType U_EXPORT2
-ucfpos_getConstraintType(
- const UConstrainedFieldPosition* ucfpos,
- UErrorCode* ec);
-
-
/**
* Gets the field category for the current position.
*
UErrorCode* ec);
+/**
+ * Determines whether a given field should be included given the
+ * constraints.
+ *
+ * Intended to be used by FormattedValue implementations.
+ *
+ * @param ucfpos The instance of UConstrainedFieldPosition.
+ * @param category The category to test.
+ * @param field The field to test.
+ * @param ec Set if an error occurs.
+ * @draft ICU 64
+ */
+U_DRAFT UBool U_EXPORT2
+ucfpos_matchesField(
+ const UConstrainedFieldPosition* ucfpos,
+ int32_t category,
+ int32_t field,
+ UErrorCode* ec);
+
+
/**
* Sets new values for the primary public getters.
*
static void AssertAllPartsEqual(
const char* messagePrefix,
const UConstrainedFieldPosition* ucfpos,
- UCFPosConstraintType constraint,
+ int32_t matching,
UFieldCategory category,
int32_t field,
int32_t start,
AssertAllPartsEqual(
"basic",
ucfpos,
- UCFPOS_CONSTRAINT_NONE,
+ 7,
UFIELD_CATEGORY_UNDEFINED,
0,
0,
AssertAllPartsEqual(
"setters 0",
ucfpos,
- UCFPOS_CONSTRAINT_CATEGORY,
+ 4,
UFIELD_CATEGORY_DATE,
0,
0,
AssertAllPartsEqual(
"setters 1",
ucfpos,
- UCFPOS_CONSTRAINT_FIELD,
+ 2,
UFIELD_CATEGORY_NUMBER,
UNUM_COMPACT_FIELD,
0,
AssertAllPartsEqual(
"setters 2",
ucfpos,
- UCFPOS_CONSTRAINT_FIELD,
+ 2,
UFIELD_CATEGORY_NUMBER,
UNUM_COMPACT_FIELD,
0,
AssertAllPartsEqual(
"setters 3",
ucfpos,
- UCFPOS_CONSTRAINT_FIELD,
+ 2,
UFIELD_CATEGORY_NUMBER,
UNUM_COMPACT_FIELD,
5,
AssertAllPartsEqual(
"setters 4",
ucfpos,
- UCFPOS_CONSTRAINT_NONE,
+ 7,
UFIELD_CATEGORY_UNDEFINED,
0,
0,
ucfpos_close(ucfpos);
}
+/** For matching, turn on these bits:
+ *
+ * 1 = UNUM_INTEGER_FIELD
+ * 2 = UNUM_COMPACT_FIELD
+ * 4 = UDAT_AM_PM_FIELD
+ */
static void AssertAllPartsEqual(
const char* messagePrefix,
const UConstrainedFieldPosition* ucfpos,
- UCFPosConstraintType constraint,
+ int32_t matching,
UFieldCategory category,
int32_t field,
int32_t start,
#define AAPE_MSG(suffix) (uprv_strncpy(message+prefixEnd, suffix, 256-prefixEnd)-prefixEnd)
- UCFPosConstraintType _constraintType = ucfpos_getConstraintType(ucfpos, &status);
- assertSuccess(AAPE_MSG("constraint"), &status);
- assertIntEquals(AAPE_MSG("constraint"), constraint, _constraintType);
-
UFieldCategory _category = ucfpos_getCategory(ucfpos, &status);
assertSuccess(AAPE_MSG("_"), &status);
assertIntEquals(AAPE_MSG("category"), category, _category);
int64_t _context = ucfpos_getInt64IterationContext(ucfpos, &status);
assertSuccess(AAPE_MSG("context"), &status);
assertIntEquals(AAPE_MSG("context"), context, _context);
+
+ UBool _matchesInteger = ucfpos_matchesField(ucfpos, UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD, &status);
+ assertSuccess(AAPE_MSG("integer field"), &status);
+ assertTrue(AAPE_MSG("integer field"),
+ ((matching & 1) != 0) ? _matchesInteger : !_matchesInteger);
+
+ UBool _matchesCompact = ucfpos_matchesField(ucfpos, UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD, &status);
+ assertSuccess(AAPE_MSG("compact field"), &status);
+ assertTrue(AAPE_MSG("compact field"),
+ ((matching & 2) != 0) ? _matchesCompact : !_matchesCompact);
+
+ UBool _matchesDate = ucfpos_matchesField(ucfpos, UFIELD_CATEGORY_DATE, UDAT_AM_PM_FIELD, &status);
+ assertSuccess(AAPE_MSG("date field"), &status);
+ assertTrue(AAPE_MSG("date field"),
+ ((matching & 4) != 0) ? _matchesDate : !_matchesDate);
}
#include "unicode/formattedvalue.h"
#include "unicode/unum.h"
+#include "unicode/udat.h"
#include "intltest.h"
#include "itformat.h"
void assertAllPartsEqual(
UnicodeString messagePrefix,
const ConstrainedFieldPosition& cfpos,
- UCFPosConstraintType constraint,
+ int32_t matching,
UFieldCategory category,
int32_t field,
int32_t start,
assertAllPartsEqual(
u"basic",
cfpos,
- UCFPOS_CONSTRAINT_NONE,
+ 7,
UFIELD_CATEGORY_UNDEFINED,
0,
0,
assertAllPartsEqual(
u"setters 0",
cfpos,
- UCFPOS_CONSTRAINT_CATEGORY,
+ 4,
UFIELD_CATEGORY_DATE,
0,
0,
assertAllPartsEqual(
u"setters 1",
cfpos,
- UCFPOS_CONSTRAINT_FIELD,
+ 2,
UFIELD_CATEGORY_NUMBER,
UNUM_COMPACT_FIELD,
0,
assertAllPartsEqual(
u"setters 2",
cfpos,
- UCFPOS_CONSTRAINT_FIELD,
+ 2,
UFIELD_CATEGORY_NUMBER,
UNUM_COMPACT_FIELD,
0,
assertAllPartsEqual(
u"setters 3",
cfpos,
- UCFPOS_CONSTRAINT_FIELD,
+ 2,
UFIELD_CATEGORY_NUMBER,
UNUM_COMPACT_FIELD,
5,
assertAllPartsEqual(
u"setters 4",
cfpos,
- UCFPOS_CONSTRAINT_NONE,
+ 7,
UFIELD_CATEGORY_UNDEFINED,
0,
0,
LocalUConstrainedFieldPositionPointer ucfpos(ucfpos_open(&status));
assertSuccess("Openining LocalUConstrainedFieldPositionPointer", status);
assertEquals(u"Test that object is valid",
- UCFPOS_CONSTRAINT_NONE,
- ucfpos_getConstraintType(ucfpos.getAlias(), &status));
+ 0LL,
+ ucfpos_getInt64IterationContext(ucfpos.getAlias(), &status));
assertSuccess("Using LocalUConstrainedFieldPositionPointer", status);
}
+/** For matching, turn on these bits:
+ *
+ * 1 = UNUM_INTEGER_FIELD
+ * 2 = UNUM_COMPACT_FIELD
+ * 4 = UDAT_AM_PM_FIELD
+ */
void FormattedValueTest::assertAllPartsEqual(
UnicodeString messagePrefix,
const ConstrainedFieldPosition& cfpos,
- UCFPosConstraintType constraint,
+ int32_t matching,
UFieldCategory category,
int32_t field,
int32_t start,
int32_t limit,
int64_t context) {
- assertEquals(messagePrefix + u": constraint",
- constraint, cfpos.getConstraintType());
assertEquals(messagePrefix + u": category",
category, cfpos.getCategory());
assertEquals(messagePrefix + u": field",
limit, cfpos.getLimit());
assertEquals(messagePrefix + u": context",
context, cfpos.getInt64IterationContext());
+
+ assertEquals(messagePrefix + u": integer field",
+ (UBool) ((matching & 1) != 0), cfpos.matchesField(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD));
+ assertEquals(messagePrefix + u": compact field",
+ (UBool) ((matching & 2) != 0), cfpos.matchesField(UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD));
+ assertEquals(messagePrefix + u": date field",
+ (UBool) ((matching & 4) != 0), cfpos.matchesField(UFIELD_CATEGORY_DATE, UDAT_AM_PM_FIELD));
}
* Represents the type of constraint for ConstrainedFieldPosition.
*
* Constraints are used to control the behavior of iteration in FormattedValue.
- *
- * @draft ICU 64
- * @provisional This API might change or be removed in a future release.
*/
- public enum ConstraintType {
+ private enum ConstraintType {
/**
* Represents the lack of a constraint.
*
- * This is the return value of {@link #getConstraintType}
+ * This is the value of fConstraint
* if no "constrain" methods were called.
- *
- * @draft ICU 64
- * @provisional This API might change or be removed in a future release.
*/
NONE,
/**
* Represents that the field class is constrained.
- * Use {@link #getClassConstraint} to access the class.
*
- * This is the return value of @link #getConstraintType}
+ * This is the value of fConstraint
* after {@link #constrainClass} is called.
*
- * FormattedValue implementations should not change the field when this constraint is active.
- *
- * @draft ICU 64
- * @provisional This API might change or be removed in a future release.
+ * FormattedValue implementations should not change the field class when this constraint is active.
*/
CLASS,
/**
* Represents that the field is constrained.
- * Use {@link #getField} to access the field.
*
- * This is the return value of @link #getConstraintType}
+ * This is the value of fConstraint
* after {@link #constrainField} is called.
*
* FormattedValue implementations should not change the field when this constraint is active.
- *
- * @draft ICU 64
- * @provisional This API might change or be removed in a future release.
*/
FIELD
};
fField = null;
}
- /**
- * Gets the currently active constraint.
- *
- * @return The currently active constraint type.
- * @draft ICU 64
- * @provisional This API might change or be removed in a future release.
- */
- public ConstraintType getConstraintType() {
- return fConstraint;
- }
-
- /**
- * Gets the class on which field positions are currently constrained.
- *
- * @return The class constraint from {@link #constrainClass}, or Object.class by default.
- * @draft ICU 64
- * @provisional This API might change or be removed in a future release.
- */
- public Class<?> getClassConstraint() {
- return fClassConstraint;
- }
-
/**
* Gets the field for the current position.
*
- * If a field constraint was set, this function returns the constrained
- * field. Otherwise, the return value is well-defined and non-null only after
+ * The return value is well-defined and non-null only after
* FormattedValue#nextPosition returns TRUE.
*
* @return The field saved in the instance. See above for null conditions.
* @provisional This API might change or be removed in a future release.
*/
public void setState(Field field, Object value, int start, int limit) {
+ // Check matchesField only as an assertion (debug build)
+ assert matchesField(field);
+
fField = field;
fValue = value;
fStart = start;
fLimit = limit;
}
- /** @internal */
+ /**
+ * Determines whether a given field should be included given the
+ * constraints.
+ *
+ * Intended to be used by FormattedValue implementations.
+ *
+ * @param field The field to test.
+ * @return Whether the field should be included given the constraints.
+ * @draft ICU 64
+ * @provisional This API might change or be removed in a future release.
+ */
public boolean matchesField(Field field) {
- // If this method ever becomes public, change assert to throw IllegalArgumentException
- assert field != null;
+ if (field == null) {
+ throw new IllegalArgumentException("field must not be null");
+ }
switch (fConstraint) {
case NONE:
return true;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.math.BigDecimal;
import java.text.AttributedCharacterIterator;
import org.junit.Test;
import com.ibm.icu.text.ConstrainedFieldPosition;
-import com.ibm.icu.text.ConstrainedFieldPosition.ConstraintType;
+import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.FormattedValue;
import com.ibm.icu.text.NumberFormat;
assertAllPartsEqual(
"basic",
cfpos,
- ConstraintType.NONE,
- Object.class,
+ 7,
null,
null,
0,
assertAllPartsEqual(
"setters 1",
cfpos,
- ConstraintType.FIELD,
- Object.class,
+ 2,
NumberFormat.Field.COMPACT,
null,
0,
assertAllPartsEqual(
"setters 1.5",
cfpos,
- ConstraintType.CLASS,
- NumberFormat.Field.class,
+ 3,
null,
null,
0,
assertAllPartsEqual(
"setters 2",
cfpos,
- ConstraintType.CLASS,
- NumberFormat.Field.class,
+ 3,
null,
null,
0,
assertAllPartsEqual(
"setters 3",
cfpos,
- ConstraintType.CLASS,
- NumberFormat.Field.class,
+ 3,
NumberFormat.Field.COMPACT,
BigDecimal.ONE,
5,
assertAllPartsEqual(
"setters 4",
cfpos,
- ConstraintType.NONE,
- Object.class,
+ 7,
null,
null,
0,
0L);
}
- private void assertAllPartsEqual(String messagePrefix, ConstrainedFieldPosition cfpos, ConstraintType constraint,
- Class<?> classConstraint, Field field, Object value, int start, int limit, long context) {
- assertEquals(messagePrefix + ": constraint", constraint, cfpos.getConstraintType());
- assertEquals(messagePrefix + ": class constraint", classConstraint, cfpos.getClassConstraint());
+ @Test
+ public void testIllegalArgumentException() {
+ ConstrainedFieldPosition cfpos = new ConstrainedFieldPosition();
+ try {
+ cfpos.matchesField(null);
+ fail("Expected an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // pass
+ }
+ }
+
+ private void assertAllPartsEqual(
+ String messagePrefix,
+ ConstrainedFieldPosition cfpos,
+ int matching,
+ Field field,
+ Object value,
+ int start,
+ int limit,
+ long context) {
assertEquals(messagePrefix + ": field", field, cfpos.getField());
assertEquals(messagePrefix + ": field value", value, cfpos.getFieldValue());
assertEquals(messagePrefix + ": start", start, cfpos.getStart());
assertEquals(messagePrefix + ": limit", limit, cfpos.getLimit());
assertEquals(messagePrefix + ": context", context, cfpos.getInt64IterationContext());
+
+ assertEquals(messagePrefix + ": integer field",
+ ((matching & 1) != 0), cfpos.matchesField(NumberFormat.Field.INTEGER));
+ assertEquals(messagePrefix + ": compact field",
+ ((matching & 2) != 0), cfpos.matchesField(NumberFormat.Field.COMPACT));
+ assertEquals(messagePrefix + ": date field",
+ ((matching & 4) != 0), cfpos.matchesField(DateFormat.Field.AM_PM));
}
public static void checkFormattedValue(String message, FormattedValue fv, String expectedString,