ICU-20138 Adding matchesField as draft and removing getConstraintType.

This commit is contained in:
Shane Carr 2019-02-13 14:37:30 -08:00 committed by Shane F. Carr
parent c05eee688c
commit d243867c11
8 changed files with 211 additions and 189 deletions

View File

@ -20,6 +20,50 @@
#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

View File

@ -40,18 +40,7 @@ void ConstrainedFieldPosition::setInt64IterationContext(int64_t context) {
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;
@ -64,6 +53,17 @@ UBool ConstrainedFieldPosition::matchesField(int32_t category, int32_t field) {
}
}
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;
@ -115,15 +115,6 @@ ucfpos_constrainField(UConstrainedFieldPosition* ptr, int32_t category, int32_t
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);
@ -170,6 +161,15 @@ ucfpos_setInt64IterationContext(UConstrainedFieldPosition* ptr, int64_t context,
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,

View File

@ -110,21 +110,10 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory {
*/
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.
@ -137,8 +126,7 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory {
/**
* 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.
@ -201,6 +189,18 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory {
*/
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.
*
@ -221,16 +221,13 @@ class U_I18N_API ConstrainedFieldPosition : public UMemory {
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;
};

View File

@ -89,55 +89,6 @@ typedef enum UFieldCategory {
} 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.
@ -257,20 +208,6 @@ ucfpos_constrainField(
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.
*
@ -361,6 +298,26 @@ ucfpos_setInt64IterationContext(
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.
*

View File

@ -20,7 +20,7 @@ static void TestSetters(void);
static void AssertAllPartsEqual(
const char* messagePrefix,
const UConstrainedFieldPosition* ucfpos,
UCFPosConstraintType constraint,
int32_t matching,
UFieldCategory category,
int32_t field,
int32_t start,
@ -46,7 +46,7 @@ static void TestBasic() {
AssertAllPartsEqual(
"basic",
ucfpos,
UCFPOS_CONSTRAINT_NONE,
7,
UFIELD_CATEGORY_UNDEFINED,
0,
0,
@ -67,7 +67,7 @@ void TestSetters() {
AssertAllPartsEqual(
"setters 0",
ucfpos,
UCFPOS_CONSTRAINT_CATEGORY,
4,
UFIELD_CATEGORY_DATE,
0,
0,
@ -79,7 +79,7 @@ void TestSetters() {
AssertAllPartsEqual(
"setters 1",
ucfpos,
UCFPOS_CONSTRAINT_FIELD,
2,
UFIELD_CATEGORY_NUMBER,
UNUM_COMPACT_FIELD,
0,
@ -91,7 +91,7 @@ void TestSetters() {
AssertAllPartsEqual(
"setters 2",
ucfpos,
UCFPOS_CONSTRAINT_FIELD,
2,
UFIELD_CATEGORY_NUMBER,
UNUM_COMPACT_FIELD,
0,
@ -103,7 +103,7 @@ void TestSetters() {
AssertAllPartsEqual(
"setters 3",
ucfpos,
UCFPOS_CONSTRAINT_FIELD,
2,
UFIELD_CATEGORY_NUMBER,
UNUM_COMPACT_FIELD,
5,
@ -115,7 +115,7 @@ void TestSetters() {
AssertAllPartsEqual(
"setters 4",
ucfpos,
UCFPOS_CONSTRAINT_NONE,
7,
UFIELD_CATEGORY_UNDEFINED,
0,
0,
@ -125,10 +125,16 @@ void TestSetters() {
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,
@ -146,10 +152,6 @@ static void AssertAllPartsEqual(
#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);
@ -167,6 +169,21 @@ static void AssertAllPartsEqual(
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);
}

View File

@ -9,6 +9,7 @@
#include "unicode/formattedvalue.h"
#include "unicode/unum.h"
#include "unicode/udat.h"
#include "intltest.h"
#include "itformat.h"
@ -24,7 +25,7 @@ private:
void assertAllPartsEqual(
UnicodeString messagePrefix,
const ConstrainedFieldPosition& cfpos,
UCFPosConstraintType constraint,
int32_t matching,
UFieldCategory category,
int32_t field,
int32_t start,
@ -50,7 +51,7 @@ void FormattedValueTest::testBasic() {
assertAllPartsEqual(
u"basic",
cfpos,
UCFPOS_CONSTRAINT_NONE,
7,
UFIELD_CATEGORY_UNDEFINED,
0,
0,
@ -66,7 +67,7 @@ void FormattedValueTest::testSetters() {
assertAllPartsEqual(
u"setters 0",
cfpos,
UCFPOS_CONSTRAINT_CATEGORY,
4,
UFIELD_CATEGORY_DATE,
0,
0,
@ -77,7 +78,7 @@ void FormattedValueTest::testSetters() {
assertAllPartsEqual(
u"setters 1",
cfpos,
UCFPOS_CONSTRAINT_FIELD,
2,
UFIELD_CATEGORY_NUMBER,
UNUM_COMPACT_FIELD,
0,
@ -88,7 +89,7 @@ void FormattedValueTest::testSetters() {
assertAllPartsEqual(
u"setters 2",
cfpos,
UCFPOS_CONSTRAINT_FIELD,
2,
UFIELD_CATEGORY_NUMBER,
UNUM_COMPACT_FIELD,
0,
@ -99,7 +100,7 @@ void FormattedValueTest::testSetters() {
assertAllPartsEqual(
u"setters 3",
cfpos,
UCFPOS_CONSTRAINT_FIELD,
2,
UFIELD_CATEGORY_NUMBER,
UNUM_COMPACT_FIELD,
5,
@ -110,7 +111,7 @@ void FormattedValueTest::testSetters() {
assertAllPartsEqual(
u"setters 4",
cfpos,
UCFPOS_CONSTRAINT_NONE,
7,
UFIELD_CATEGORY_UNDEFINED,
0,
0,
@ -123,22 +124,26 @@ void FormattedValueTest::testLocalPointer() {
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",
@ -149,6 +154,13 @@ void FormattedValueTest::assertAllPartsEqual(
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));
}

View File

@ -23,47 +23,33 @@ public class ConstrainedFieldPosition {
* 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
};
@ -174,33 +160,10 @@ public class ConstrainedFieldPosition {
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.
@ -299,16 +262,30 @@ public class ConstrainedFieldPosition {
* @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;

View File

@ -5,6 +5,7 @@ package com.ibm.icu.dev.test.format;
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;
@ -16,7 +17,7 @@ import java.util.Set;
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;
@ -30,8 +31,7 @@ public class FormattedValueTest {
assertAllPartsEqual(
"basic",
cfpos,
ConstraintType.NONE,
Object.class,
7,
null,
null,
0,
@ -47,8 +47,7 @@ public class FormattedValueTest {
assertAllPartsEqual(
"setters 1",
cfpos,
ConstraintType.FIELD,
Object.class,
2,
NumberFormat.Field.COMPACT,
null,
0,
@ -59,8 +58,7 @@ public class FormattedValueTest {
assertAllPartsEqual(
"setters 1.5",
cfpos,
ConstraintType.CLASS,
NumberFormat.Field.class,
3,
null,
null,
0,
@ -71,8 +69,7 @@ public class FormattedValueTest {
assertAllPartsEqual(
"setters 2",
cfpos,
ConstraintType.CLASS,
NumberFormat.Field.class,
3,
null,
null,
0,
@ -83,8 +80,7 @@ public class FormattedValueTest {
assertAllPartsEqual(
"setters 3",
cfpos,
ConstraintType.CLASS,
NumberFormat.Field.class,
3,
NumberFormat.Field.COMPACT,
BigDecimal.ONE,
5,
@ -95,8 +91,7 @@ public class FormattedValueTest {
assertAllPartsEqual(
"setters 4",
cfpos,
ConstraintType.NONE,
Object.class,
7,
null,
null,
0,
@ -104,15 +99,38 @@ public class FormattedValueTest {
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,